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

feature/appm-store/pbac
Jayasanka 6 years ago
commit 9180df4fbf

@ -49,9 +49,9 @@ public class LifecycleState {
value = "Timestamp of the lifecycle has been updated") value = "Timestamp of the lifecycle has been updated")
private Timestamp updatedAt; private Timestamp updatedAt;
@ApiModelProperty(name = "resonForChange", @ApiModelProperty(name = "reasonForChange",
value = "Reason for the application release lifecycle change from previous state to current state.") value = "Reason for the application release lifecycle change from previous state to current state.")
private String resonForChange; private String reasonForChange;
public String getCurrentState() { public String getCurrentState() {
return currentState; return currentState;
@ -93,7 +93,7 @@ public class LifecycleState {
this.nextStates = nextStates; this.nextStates = nextStates;
} }
public String getResonForChange() { return resonForChange; } public String getReasonForChange() { return reasonForChange; }
public void setResonForChange(String resonForChange) { this.resonForChange = resonForChange; } public void setReasonForChange(String reasonForChange) { this.reasonForChange = reasonForChange; }
} }

@ -2,7 +2,7 @@ package org.wso2.carbon.device.application.mgt.common.config;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
public class FailureCallback { public class ErrorCallback {
private String badRequest; private String badRequest;
private String unauthorized; private String unauthorized;

@ -1,27 +0,0 @@
package org.wso2.carbon.device.application.mgt.common.config;
import javax.xml.bind.annotation.XmlElement;
public class LoginResponse {
private String successCallback;
private FailureCallback failureCallback;
@XmlElement(name = "SuccessCallback", required=true)
public String getSuccessCallback() {
return successCallback;
}
public void setSuccessCallback(String successCallback) {
this.successCallback = successCallback;
}
@XmlElement(name = "FailureCallback", required=true)
public FailureCallback getFailureCallback() {
return failureCallback;
}
public void setFailureCallback(FailureCallback failureCallback) {
this.failureCallback = failureCallback;
}
}

@ -9,7 +9,7 @@ public class UIConfiguration {
private AppRegistration appRegistration; private AppRegistration appRegistration;
private List<String> scopes; private List<String> scopes;
private boolean isSsoEnable; private boolean isSsoEnable;
private LoginResponse loginResponse; private ErrorCallback errorCallback;
@XmlElement(name = "AppRegistration", required=true) @XmlElement(name = "AppRegistration", required=true)
public AppRegistration getAppRegistration() { public AppRegistration getAppRegistration() {
@ -39,12 +39,8 @@ public class UIConfiguration {
isSsoEnable = ssoEnable; isSsoEnable = ssoEnable;
} }
public LoginResponse getLoginResponse() { @XmlElement(name = "ErrorCallback", required=true)
return loginResponse; public ErrorCallback getErrorCallback() { return errorCallback; }
}
@XmlElement(name = "LoginResponse", required=true) public void setErrorCallback(ErrorCallback errorCallback) { this.errorCallback = errorCallback; }
public void setLoginResponse(LoginResponse loginResponse) {
this.loginResponse = loginResponse;
}
} }

@ -45,15 +45,16 @@ import java.util.List;
*/ */
public interface ApplicationManager { public interface ApplicationManager {
/** /***
* Creates an application. * The method is responsible to add new application into entgra App Manager.
* *
* @param applicationWrapper Application that need to be created. * @param applicationWrapper Application that need to be created.
* @return Created application * @param applicationArtifact contains artifact data. i.e image name and stream, icon name and stream etc.
* @throws ApplicationManagementException ApplicationDTO Management Exception * @return {@link Application}
* @throws ApplicationManagementException Catch all other throwing exceptions and throw {@link ApplicationManagementException}
*/ */
Application createApplication(ApplicationWrapper applicationWrapper, ApplicationArtifact applicationArtifact) Application createApplication(ApplicationWrapper applicationWrapper, ApplicationArtifact applicationArtifact)
throws ApplicationManagementException, RequestValidatingException; throws ApplicationManagementException;
Application createWebClip(WebAppWrapper webAppWrapper, ApplicationArtifact applicationArtifact) Application createWebClip(WebAppWrapper webAppWrapper, ApplicationArtifact applicationArtifact)
throws ApplicationManagementException; throws ApplicationManagementException;
@ -134,15 +135,6 @@ public interface ApplicationManager {
*/ */
Application getApplicationByUuid(String uuid, String state) throws ApplicationManagementException; Application getApplicationByUuid(String uuid, String state) throws ApplicationManagementException;
/**
* To get an application associated with the release.
*
* @param appReleaseUUID UUID of the app release
* @return {@link ApplicationDTO} associated with the release
* @throws ApplicationManagementException If unable to retrieve {@link ApplicationDTO} associated with the given UUID
*/
ApplicationDTO getApplicationByRelease(String appReleaseUUID) throws ApplicationManagementException;
/** /**
* To get lifecycle state change flow of a particular Application Release. * To get lifecycle state change flow of a particular Application Release.
* *

@ -54,7 +54,9 @@ public class ApplicationReleaseWrapper {
private String metaData; private String metaData;
@ApiModelProperty(name = "supportedOsVersions", @ApiModelProperty(name = "supportedOsVersions",
value = "ApplicationDTO release supported OS versions") value = "Application release supported OS versions",
required = true,
example = "4.0-10.0")
@NotNull @NotNull
private String supportedOsVersions; private String supportedOsVersions;

@ -66,7 +66,9 @@ public class PublicAppReleaseWrapper {
private String packageName; private String packageName;
@ApiModelProperty(name = "supportedOsVersions", @ApiModelProperty(name = "supportedOsVersions",
value = "ApplicationDTO release supported OS versions") value = "Application release supported OS versions",
required = true,
example = "4.0-10.0")
@NotNull @NotNull
private String supportedOsVersions; private String supportedOsVersions;

@ -20,7 +20,6 @@ package org.wso2.carbon.device.application.mgt.core.dao;
import org.wso2.carbon.device.application.mgt.common.*; import org.wso2.carbon.device.application.mgt.common.*;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO; import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationReleaseDTO;
import org.wso2.carbon.device.application.mgt.common.dto.CategoryDTO; import org.wso2.carbon.device.application.mgt.common.dto.CategoryDTO;
import org.wso2.carbon.device.application.mgt.common.dto.TagDTO; import org.wso2.carbon.device.application.mgt.common.dto.TagDTO;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException; import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
@ -101,18 +100,6 @@ public interface ApplicationDAO {
void updateCategory(CategoryDTO categoryDTO, int tenantId) throws ApplicationManagementDAOException; void updateCategory(CategoryDTO categoryDTO, int tenantId) throws ApplicationManagementDAOException;
/**
* To check application existence.
*
* @param appName appName that need to identify application.
* @param type type that need to identify application.
* @param tenantId tenantId that need to identify application.
* @throws ApplicationManagementDAOException ApplicationDTO Management DAO Exception.
*/
boolean isExistApplication(String appName, String type, int tenantId) throws ApplicationManagementDAOException;
/** /**
* To get the applications that satisfy the given criteria. * To get the applications that satisfy the given criteria.
* *
@ -132,27 +119,6 @@ public interface ApplicationDAO {
*/ */
String getUuidOfLatestRelease(int appId) throws ApplicationManagementDAOException; String getUuidOfLatestRelease(int appId) throws ApplicationManagementDAOException;
/**
* To get the application with the given uuid
*
* @param appName name of the application to be retrieved.
* @param tenantId ID of the tenant.
* @param appType Type of the application.
* @return the application
* @throws ApplicationManagementDAOException ApplicationDTO Management DAO Exception.
*/
ApplicationDTO getApplication(String appName, String appType, int tenantId) throws ApplicationManagementDAOException;
/**
* To get the application with the given id
*
* @param id ID of the application.
* @param tenantId ID of the tenant.
* @return the application
* @throws ApplicationManagementDAOException ApplicationDTO Management DAO Exception.
*/
ApplicationDTO getApplicationById(String id, int tenantId) throws ApplicationManagementDAOException;
/** /**
* To get the application with the given id * To get the application with the given id
* *
@ -173,16 +139,6 @@ public interface ApplicationDAO {
*/ */
ApplicationDTO getApplicationByUUID(String releaseUuid, int tenantId) throws ApplicationManagementDAOException; ApplicationDTO getApplicationByUUID(String releaseUuid, int tenantId) throws ApplicationManagementDAOException;
/**
* To get the application with the given uuid
*
* @param appId ID of the application
* @param tenantId Tenant Id
* @return the boolean value
* @throws ApplicationManagementDAOException ApplicationDTO Management DAO Exception.
*/
boolean verifyApplicationExistenceById(int appId, int tenantId) throws ApplicationManagementDAOException;
/** /**
* Verify whether application exist for given application name and device type. Because a name and device type is * Verify whether application exist for given application name and device type. Because a name and device type is
* unique for an application. * unique for an application.
@ -193,7 +149,7 @@ public interface ApplicationDAO {
* @return ID of the ApplicationDTO. * @return ID of the ApplicationDTO.
* @throws ApplicationManagementDAOException Application Management DAO Exception. * @throws ApplicationManagementDAOException Application Management DAO Exception.
*/ */
boolean isValidAppName(String appName, int deviceTypeId, int tenantId) throws ApplicationManagementDAOException; boolean isExistingAppName(String appName, int deviceTypeId, int tenantId) throws ApplicationManagementDAOException;
/** /**
* To edit the given application. * To edit the given application.
@ -236,16 +192,6 @@ public interface ApplicationDAO {
*/ */
void deleteTags(List<String> tags, int applicationId, int tenantId) throws ApplicationManagementDAOException; void deleteTags(List<String> tags, int applicationId, int tenantId) throws ApplicationManagementDAOException;
/**
* To get an {@link ApplicationDTO} associated with the given release
*
* @param appReleaseUUID UUID of the {@link ApplicationReleaseDTO}
* @param tenantId ID of the tenant
* @return {@link ApplicationDTO} associated with the given release UUID
* @throws ApplicationManagementDAOException if unable to fetch the ApplicationDTO from the data store.
*/
ApplicationDTO getApplicationByRelease(String appReleaseUUID, int tenantId) throws ApplicationManagementDAOException;
String getApplicationSubTypeByUUID(String uuid, int tenantId) throws ApplicationManagementDAOException; String getApplicationSubTypeByUUID(String uuid, int tenantId) throws ApplicationManagementDAOException;
void deleteApplication(int appId, int tenantId) throws ApplicationManagementDAOException; void deleteApplication(int appId, int tenantId) throws ApplicationManagementDAOException;

@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory;
import org.json.JSONException; import org.json.JSONException;
import org.wso2.carbon.device.application.mgt.common.AppLifecycleState; import org.wso2.carbon.device.application.mgt.common.AppLifecycleState;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO; import org.wso2.carbon.device.application.mgt.common.dto.ApplicationDTO;
import org.wso2.carbon.device.application.mgt.common.dto.ApplicationReleaseDTO;
import org.wso2.carbon.device.application.mgt.common.dto.CategoryDTO; import org.wso2.carbon.device.application.mgt.common.dto.CategoryDTO;
import org.wso2.carbon.device.application.mgt.common.Filter; import org.wso2.carbon.device.application.mgt.common.Filter;
import org.wso2.carbon.device.application.mgt.common.dto.TagDTO; import org.wso2.carbon.device.application.mgt.common.dto.TagDTO;
@ -94,36 +93,6 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
} }
} }
@Override
public boolean isExistApplication(String appName, String type, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Request received in DAO Layer to verify whether the registering app is registered or not");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = "SELECT * FROM AP_APP WHERE NAME = ? AND TYPE = ? AND TENANT_ID = ?";
try {
conn = this.getDBConnection();
conn.setAutoCommit(false);
stmt = conn.prepareStatement(sql);
stmt.setString(1, appName);
stmt.setString(2, type);
stmt.setInt(3, tenantId);
rs = stmt.executeQuery();
return rs.next();
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException(
"Error occurred while obtaining the DB connection when verifying application existence", e);
} catch (SQLException e) {
throw new ApplicationManagementDAOException(
"DB connection error occured while checking whether application exist or not.", e);
} finally {
DAOUtil.cleanupResources(stmt, rs);
}
}
@Override @Override
public List<ApplicationDTO> getApplications(Filter filter,int deviceTypeId, int tenantId) throws ApplicationManagementDAOException { public List<ApplicationDTO> getApplications(Filter filter,int deviceTypeId, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -344,96 +313,6 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
return count; return count;
} }
@Override
public ApplicationDTO getApplication(String appName, String appType, int tenantId) throws
ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Getting application with the type(" + appType + " and Name " + appName +
" ) from the database");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = this.getDBConnection();
String sql =
"SELECT AP_APP.ID AS APP_ID, AP_APP.NAME AS APP_NAME, AP_APP.TYPE AS APP_TYPE, AP_APP.APP_CATEGORY "
+ "AS APP_CATEGORY, AP_APP.SUB_TYPE AS SUB_TYPE ,AP_APP.CURRENCY AS CURRENCY,"
+ " AP_APP.RESTRICTED AS RESTRICTED, AP_APP_TAG.TAG AS APP_TAG, AP_UNRESTRICTED_ROLE.ROLE "
+ "AS ROLE FROM AP_APP, AP_APP_TAG, AP_UNRESTRICTED_ROLE WHERE AP_APP.NAME=? AND "
+ "AP_APP.TYPE= ? AND AP_APP.TENANT_ID=?;";
stmt = conn.prepareStatement(sql);
stmt.setString(1, appName);
stmt.setString(2, appType);
stmt.setInt(3, tenantId);
rs = stmt.executeQuery();
if (log.isDebugEnabled()) {
log.debug("Successfully retrieved basic details of the application with the type "
+ appType + "and app name " + appName);
}
return DAOUtil.loadApplication(rs);
} catch (SQLException e) {
throw new ApplicationManagementDAOException(
"Error occurred while getting application details with app name " + appName +
" while executing query.", e);
} catch (JSONException e) {
throw new ApplicationManagementDAOException("Error occurred while parsing JSON", e);
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} catch (UnexpectedServerErrorException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} finally {
DAOUtil.cleanupResources(stmt, rs);
}
}
@Override
public ApplicationDTO getApplicationById(String id, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Getting application with the id:" + id);
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = this.getDBConnection();
String sql =
"SELECT AP_APP.ID AS APP_ID, AP_APP.NAME AS APP_NAME, AP_APP.TYPE AS APP_TYPE, AP_APP.APP_CATEGORY "
+ "AS APP_CATEGORY, AP_APP.SUB_TYPE AS SUB_TYPE ,AP_APP.CURRENCY AS CURRENCY,"
+ " AP_APP.RESTRICTED AS RESTRICTED, AP_APP_TAG.TAG AS APP_TAG, AP_UNRESTRICTED_ROLE.ROLE "
+ "AS ROLE FROM AP_APP, AP_APP_TAG, AP_UNRESTRICTED_ROLE WHERE AP_APP.NAME=? AND "
+ "AP_APP.APP_ID= ? AND AP_APP.TENANT_ID=?;";
stmt = conn.prepareStatement(sql);
stmt.setString(1, id);
stmt.setInt(2, tenantId);
rs = stmt.executeQuery();
if (log.isDebugEnabled()) {
log.debug("Successfully retrieved basic details of the application with the id:" + id);
}
return DAOUtil.loadApplication(rs);
} catch (SQLException e) {
throw new ApplicationManagementDAOException(
"Error occurred while getting application details with app id " + id +
" while executing query.", e);
} catch (JSONException e) {
throw new ApplicationManagementDAOException("Error occurred while parsing JSON", e);
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} catch (UnexpectedServerErrorException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} finally {
DAOUtil.cleanupResources(stmt, rs);
}
}
@Override @Override
public ApplicationDTO getApplicationByUUID(String releaseUuid, int tenantId) public ApplicationDTO getApplicationByUUID(String releaseUuid, int tenantId)
throws ApplicationManagementDAOException { throws ApplicationManagementDAOException {
@ -581,39 +460,6 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
} }
} }
@Override
public boolean verifyApplicationExistenceById(int appId, int tenantId) throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Getting application with the application ID(" + appId + " ) from the database");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = this.getDBConnection();
String sql =
"SELECT AP_APP.ID AS APP_ID FROM AP_APP WHERE AP_APP.ID = ? AND AP_APP.TENANT_ID=?;";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, appId);
stmt.setInt(2, tenantId);
rs = stmt.executeQuery();
if (log.isDebugEnabled()) {
log.debug("Successfully retrieved basic details of the application with the application ID " + appId);
}
return rs.next();
} catch (SQLException e) {
throw new ApplicationManagementDAOException(
"Error occurred while getting application details with app ID " + appId + " while executing query.",
e);
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} finally {
DAOUtil.cleanupResources(stmt, rs);
}
}
@Override @Override
public boolean updateApplication(ApplicationDTO applicationDTO, int tenantId) public boolean updateApplication(ApplicationDTO applicationDTO, int tenantId)
throws ApplicationManagementDAOException { throws ApplicationManagementDAOException {
@ -1532,76 +1378,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic
} }
@Override @Override
public ApplicationDTO getApplicationByRelease(String appReleaseUUID, int tenantId) public boolean isExistingAppName(String appName, int deviceTypeId, int tenantId) throws ApplicationManagementDAOException {
throws ApplicationManagementDAOException {
if (log.isDebugEnabled()) {
log.debug("Getting application with the UUID (" + appReleaseUUID + ") from the database");
}
Connection conn;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = this.getDBConnection();
String sql = "SELECT AP_APP_RELEASE.ID AS RELEASE_ID, AP_APP_RELEASE.VERSION, AP_APP_RELEASE.TENANT_ID,"
+ "AP_APP_RELEASE.UUID, AP_APP_RELEASE.RELEASE_TYPE, AP_APP_RELEASE.APP_PRICE, "
+ "AP_APP_RELEASE.STORED_LOCATION, AP_APP_RELEASE.BANNER_LOCATION, AP_APP_RELEASE.SC_1_LOCATION,"
+ "AP_APP_RELEASE.SC_2_LOCATION, AP_APP_RELEASE.SC_3_LOCATION, AP_APP_RELEASE.APP_HASH_VALUE,"
+ "AP_APP_RELEASE.SHARED_WITH_ALL_TENANTS, AP_APP_RELEASE.APP_META_INFO, AP_APP_RELEASE.CREATED_BY,"
+ "AP_APP_RELEASE.CREATED_AT, AP_APP_RELEASE.PUBLISHED_BY, AP_APP_RELEASE.PUBLISHED_AT, "
+ "AP_APP_RELEASE.STARS,"
+ "AP_APP.ID AS APP_ID, AP_APP.NAME AS APP_NAME, AP_APP.TYPE AS APP_TYPE, "
+ "AP_APP.APP_CATEGORY AS APP_CATEGORY, AP_APP.SUB_TYPE AS SUB_TYPE, AP_APP.CURRENCY AS CURRENCY, "
+ "AP_UNRESTRICTED_ROLE.ROLE AS ROLE FROM AP_APP, AP_UNRESTRICTED_ROLE, AP_APP_RELEASE "
+ "WHERE AP_APP_RELEASE.UUID=? AND AP_APP.TENANT_ID=?;";
stmt = conn.prepareStatement(sql);
stmt.setString(1, appReleaseUUID);
stmt.setInt(2, tenantId);
rs = stmt.executeQuery();
if (log.isDebugEnabled()) {
log.debug("Successfully retrieved details of the application with the UUID " + appReleaseUUID);
}
ApplicationDTO application = null;
while (rs.next()) {
ApplicationReleaseDTO appRelease = DAOUtil.loadApplicationRelease(rs);
application = new ApplicationDTO();
application.setId(rs.getInt("APP_ID"));
application.setName(rs.getString("APP_NAME"));
application.setType(rs.getString("APP_TYPE"));
// application.setAppCategories(rs.getString("APP_CATEGORY"));
application.setSubType(rs.getString("SUB_TYPE"));
application.setPaymentCurrency(rs.getString("CURRENCY"));
// application.setIsRestricted(rs.getBoolean("RESTRICTED"));
String unrestrictedRole = rs.getString("ROLE").toLowerCase();
List<String> unrestrictedRoleList = new ArrayList<>();
unrestrictedRoleList.add(unrestrictedRole);
application.setUnrestrictedRoles(unrestrictedRoleList);
List<ApplicationReleaseDTO> applicationReleaseList = new ArrayList<>();
applicationReleaseList.add(appRelease);
application.setApplicationReleaseDTOs(applicationReleaseList);
}
return application;
} catch (SQLException e) {
throw new ApplicationManagementDAOException("Error occurred while getting application details with UUID "
+ appReleaseUUID + " while executing query.", e);
} catch (JSONException e) {
throw new ApplicationManagementDAOException("Error occurred while parsing JSON", e);
} catch (DBConnectionException e) {
throw new ApplicationManagementDAOException("Error occurred while obtaining the DB connection.", e);
} finally {
DAOUtil.cleanupResources(stmt, rs);
}
}
@Override
public boolean isValidAppName(String appName, int deviceTypeId, int tenantId) throws ApplicationManagementDAOException {
Connection conn; Connection conn;
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet rs = null; ResultSet rs = null;

@ -188,7 +188,7 @@ public class GenericLifecycleStateDAOImpl extends AbstractDAOImpl implements Lif
stmt.setInt(3, tenantId); stmt.setInt(3, tenantId);
stmt.setString(4, state.getUpdatedBy()); stmt.setString(4, state.getUpdatedBy());
stmt.setTimestamp(5, timestamp); stmt.setTimestamp(5, timestamp);
stmt.setString(6, state.getResonForChange()); stmt.setString(6, state.getReasonForChange());
stmt.setInt(7, appReleaseId); stmt.setInt(7, appReleaseId);
stmt.setInt(8, appReleaseId); stmt.setInt(8, appReleaseId);
stmt.executeUpdate(); stmt.executeUpdate();

@ -25,7 +25,6 @@ import org.apache.commons.validator.routines.UrlValidator;
import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Attachment;
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.CarbonConstants;
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.application.mgt.common.ApplicationArtifact; import org.wso2.carbon.device.application.mgt.common.ApplicationArtifact;
@ -88,9 +87,9 @@ import org.wso2.carbon.device.application.mgt.core.util.StorageManagementUtil;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -131,21 +130,14 @@ public class ApplicationManagerImpl implements ApplicationManager {
this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO(); this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO();
} }
/***
* The responsbility of this method is the creating an application.
* @param applicationWrapper ApplicationDTO that need to be created.
* @return {@link ApplicationDTO}
* @throws RequestValidatingException if application creating request is invalid,
* @throws ApplicationManagementException Catch all other throwing exceptions and throw {@link ApplicationManagementException}
*/
@Override @Override
public Application createApplication(ApplicationWrapper applicationWrapper, public Application createApplication(ApplicationWrapper applicationWrapper,
ApplicationArtifact applicationArtifact) throws RequestValidatingException, ApplicationManagementException { ApplicationArtifact applicationArtifact) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Application create request is received for the tenant : " + tenantId + " From" + " the user : " log.debug("Application create request is received for the tenant : " + tenantId + " and the user: "
+ userName); + userName);
} }
@ -154,6 +146,13 @@ public class ApplicationManagerImpl implements ApplicationManager {
//uploading application artifacts //uploading application artifacts
try { try {
ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0);
if (!isValidOsVersions(applicationReleaseDTO.getSupportedOsVersions(), applicationWrapper.getDeviceType())){
String msg = "You are trying to create application which has an application release contains invalid or "
+ "unsupported OS versions in the supportedOsVersions section. Hence, please re-evaluate the "
+ "request payload.";
log.error(msg);
throw new BadRequestException(msg);
}
applicationReleaseDTO = addApplicationReleaseArtifacts(applicationDTO.getType(), applicationReleaseDTO = addApplicationReleaseArtifacts(applicationDTO.getType(),
applicationWrapper.getDeviceType(), applicationReleaseDTO, applicationArtifact, false); applicationWrapper.getDeviceType(), applicationReleaseDTO, applicationArtifact, false);
applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact); applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact);
@ -169,7 +168,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
private void deleteApplicationArtifacts(List<String> directoryPaths) throws ApplicationManagementException { private void deleteApplicationArtifacts(List<String> directoryPaths) throws ApplicationManagementException {
ApplicationStorageManager applicationStorageManager = DAOUtil.getApplicationStorageManager(); ApplicationStorageManager applicationStorageManager = DAOUtil.getApplicationStorageManager();
try { try {
applicationStorageManager.deleteAllApplicationReleaseArtifacts(directoryPaths); applicationStorageManager.deleteAllApplicationReleaseArtifacts(directoryPaths);
} catch (ApplicationStorageManagementException e) { } catch (ApplicationStorageManagementException e) {
@ -425,7 +423,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(webAppWrapper); ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(webAppWrapper);
ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
//todo check installer name exists or not, do it in the validation method
String md5 = DigestUtils.md5Hex(applicationReleaseDTO.getInstallerName()); String md5 = DigestUtils.md5Hex(applicationReleaseDTO.getInstallerName());
applicationReleaseDTO.setUuid(uuid); applicationReleaseDTO.setUuid(uuid);
applicationReleaseDTO.setAppHashValue(md5); applicationReleaseDTO.setAppHashValue(md5);
@ -455,6 +452,14 @@ public class ApplicationManagerImpl implements ApplicationManager {
+ userName); + userName);
} }
if (!isValidOsVersions(publicAppWrapper.getPublicAppReleaseWrappers().get(0).getSupportedOsVersions(),
publicAppWrapper.getDeviceType())) {
String msg = "You are trying to add application release which has invalid or unsupported OS versions in "
+ "the supportedOsVersions section. Hence, please re-evaluate the request payload.";
log.error(msg);
throw new BadRequestException(msg);
}
if (DeviceTypes.ANDROID.toString().equals(publicAppWrapper.getDeviceType())) { if (DeviceTypes.ANDROID.toString().equals(publicAppWrapper.getDeviceType())) {
publicAppStorePath = Constants.GOOGLE_PLAY_STORE_URL; publicAppStorePath = Constants.GOOGLE_PLAY_STORE_URL;
} else if (DeviceTypes.IOS.toString().equals(publicAppWrapper.getDeviceType())) { } else if (DeviceTypes.IOS.toString().equals(publicAppWrapper.getDeviceType())) {
@ -758,8 +763,15 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg); log.error(msg);
throw new BadRequestException(msg); throw new BadRequestException(msg);
} }
DeviceType deviceType = getDeviceTypeData(applicationDTO.getDeviceTypeId());
if (!isValidOsVersions(applicationReleaseWrapper.getSupportedOsVersions(), deviceType.getName())){
String msg = "You are trying to add application release which has invalid or unsupported OS versions in "
+ "the supportedOsVersions section. Hence, please re-evaluate the request payload.";
log.error(msg);
throw new BadRequestException(msg);
}
ApplicationReleaseDTO applicationReleaseDTO = uploadReleaseArtifacts(applicationReleaseWrapper, ApplicationReleaseDTO applicationReleaseDTO = uploadReleaseArtifacts(applicationReleaseWrapper,
applicationDTO, applicationArtifact); applicationDTO, applicationArtifact, deviceType.getName());
ConnectionManagerUtil.beginDBTransaction(); ConnectionManagerUtil.beginDBTransaction();
String initialstate = lifecycleStateManager.getInitialState(); String initialstate = lifecycleStateManager.getInitialState();
applicationReleaseDTO.setCurrentState(initialstate); applicationReleaseDTO.setCurrentState(initialstate);
@ -818,12 +830,11 @@ public class ApplicationManagerImpl implements ApplicationManager {
} }
private ApplicationReleaseDTO uploadReleaseArtifacts(ApplicationReleaseWrapper applicationReleaseWrapper, private ApplicationReleaseDTO uploadReleaseArtifacts(ApplicationReleaseWrapper applicationReleaseWrapper,
ApplicationDTO applicationDTO, ApplicationArtifact applicationArtifact) ApplicationDTO applicationDTO, ApplicationArtifact applicationArtifact, String deviceTypeName)
throws ApplicationManagementException { throws ApplicationManagementException {
try { try {
DeviceType deviceType = getDeviceTypeData(applicationDTO.getDeviceTypeId());
ApplicationReleaseDTO applicationReleaseDTO = addApplicationReleaseArtifacts(applicationDTO.getType(), ApplicationReleaseDTO applicationReleaseDTO = addApplicationReleaseArtifacts(applicationDTO.getType(),
deviceType.getName(), APIUtil.releaseWrapperToReleaseDTO(applicationReleaseWrapper), applicationArtifact, deviceTypeName, APIUtil.releaseWrapperToReleaseDTO(applicationReleaseWrapper), applicationArtifact,
true); true);
return addImageArtifacts(applicationReleaseDTO, applicationArtifact); return addImageArtifacts(applicationReleaseDTO, applicationArtifact);
} catch (ResourceManagementException e) { } catch (ResourceManagementException e) {
@ -834,6 +845,30 @@ public class ApplicationManagerImpl implements ApplicationManager {
} }
} }
private boolean isValidOsVersions(String osRange, String deviceTypeName)
throws ApplicationManagementException {
String lowestSupportingOsVersion;
String highestSupportingOsVersion = null;
String[] supportedOsVersionValues = osRange.split("-");
lowestSupportingOsVersion = supportedOsVersionValues[0].trim();
if (!"ALL".equals(supportedOsVersionValues[1].trim())) {
highestSupportingOsVersion = supportedOsVersionValues[1].trim();
}
try {
DeviceManagementProviderService deviceManagementProviderService = DAOUtil.getDeviceManagementService();
return deviceManagementProviderService.getDeviceTypeVersion(deviceTypeName, lowestSupportingOsVersion)
!= null && (highestSupportingOsVersion == null
|| deviceManagementProviderService.getDeviceTypeVersion(deviceTypeName, highestSupportingOsVersion)
!= null);
} catch (DeviceManagementException e) {
String msg =
"Error occurred while getting supported device type versions for device type : " + deviceTypeName;
log.error(msg);
throw new ApplicationManagementException(msg);
}
}
@Override @Override
public Application getApplicationById(int appId, String state) throws ApplicationManagementException { public Application getApplicationById(int appId, String state) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
@ -1070,107 +1105,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
return roleList; return roleList;
} }
//todo no usage
public ApplicationDTO getApplication(String appType, String appName) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
ApplicationDTO application;
boolean isAppAllowed = false;
List<ApplicationReleaseDTO> applicationReleases;
try {
ConnectionManagerUtil.openDBConnection();
application = this.applicationDAO.getApplication(appName, appType, tenantId);
if (isAdminUser(userName, tenantId, CarbonConstants.UI_ADMIN_PERMISSION_COLLECTION)) {
applicationReleases = getReleases(application, null);
application.setApplicationReleaseDTOs(applicationReleases);
return application;
}
if (!application.getUnrestrictedRoles().isEmpty()) {
if (hasUserRole(application.getUnrestrictedRoles(), userName)) {
isAppAllowed = true;
}
} else {
isAppAllowed = true;
}
if (!isAppAllowed) {
return null;
}
applicationReleases = getReleases(application, null);
application.setApplicationReleaseDTOs(applicationReleases);
return application;
} catch (UserStoreException e) {
throw new ApplicationManagementException(
"User-store exception while getting application with the " + "application name " + appName);
} catch (ApplicationManagementDAOException e) {
//todo
throw new ApplicationManagementException("");
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
@Override public ApplicationDTO getApplicationByRelease(String appReleaseUUID) throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
ApplicationDTO application;
try {
ConnectionManagerUtil.openDBConnection();
application = this.applicationDAO.getApplicationByRelease(appReleaseUUID, tenantId);
if (application.getUnrestrictedRoles().isEmpty() || hasUserRole(application.getUnrestrictedRoles(),
userName)) {
return application;
}
return null;
} catch (UserStoreException e) {
throw new ApplicationManagementException(
"User-store exception while getting application with the application UUID " + appReleaseUUID);
} catch (ApplicationManagementDAOException e) {
//todo
throw new ApplicationManagementException("");
} finally {
ConnectionManagerUtil.closeDBConnection();
}
}
// todo rethink about this method
private List<ApplicationReleaseDTO> getReleases(ApplicationDTO application, String releaseState)
throws ApplicationManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
List<ApplicationReleaseDTO> applicationReleases;
if (log.isDebugEnabled()) {
log.debug("Request is received to retrieve all the releases related with the application " + application
.toString());
}
//todo
applicationReleases = null;
try {
applicationReleases = this.applicationReleaseDAO.getReleases(application.getId(), tenantId);
} catch (ApplicationManagementDAOException e) {
//todo
throw new ApplicationManagementException("");
}
for (ApplicationReleaseDTO applicationRelease : applicationReleases) {
LifecycleState lifecycleState = null;
try {
lifecycleState = this.lifecycleStateDAO.getLatestLifeCycleStateByReleaseID(applicationRelease.getId());
} catch (LifeCycleManagementDAOException e) {
throw new ApplicationManagementException(
"Error occurred while getting the latest lifecycle state for the application release UUID: "
+ applicationRelease.getUuid(), e);
}
if (lifecycleState != null) {
log.error("todo");
// applicationRelease.setLifecycleState(lifecycleState);
}
}
return applicationReleases;
// return filterAppReleaseByCurrentState(applicationReleases, releaseState);
}
@Override @Override
public void deleteApplication(int applicationId) throws ApplicationManagementException { public void deleteApplication(int applicationId) throws ApplicationManagementException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@ -1320,39 +1254,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
} }
} }
/**
* To check whether current user has the permission to do some secured operation.
*
* @param username Name of the User.
* @param tenantId ID of the tenant.
* @param permission Permission that need to be checked.
* @return true if the current user has the permission, otherwise false.
* @throws UserStoreException UserStoreException
*/
private boolean isAdminUser(String username, int tenantId, String permission) throws UserStoreException {
UserRealm userRealm = DataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId);
return userRealm != null && userRealm.getAuthorizationManager() != null && userRealm.getAuthorizationManager()
.isUserAuthorized(MultitenantUtils.getTenantAwareUsername(username), permission,
CarbonConstants.UI_PERMISSION_ACTION);
}
/***
* To verify whether application type is valid one or not
* @param appType application type {@link ApplicationType}
* @return true returns if appType is valid on, otherwise returns false
*/
private boolean isValidAppType(String appType) {
if (appType == null) {
return false;
}
for (ApplicationType applicationType : ApplicationType.values()) {
if (applicationType.toString().equals(appType)) {
return true;
}
}
return false;
}
@Override @Override
public void updateApplicationImageArtifact(String uuid, ApplicationArtifact applicationArtifact) public void updateApplicationImageArtifact(String uuid, ApplicationArtifact applicationArtifact)
throws ApplicationManagementException { throws ApplicationManagementException {
@ -1550,7 +1451,7 @@ public class ApplicationManagerImpl implements ApplicationManager {
lifecycleState.setCurrentState(lifecycleChanger.getAction()); lifecycleState.setCurrentState(lifecycleChanger.getAction());
lifecycleState.setPreviousState(applicationReleaseDTO.getCurrentState()); lifecycleState.setPreviousState(applicationReleaseDTO.getCurrentState());
lifecycleState.setUpdatedBy(userName); lifecycleState.setUpdatedBy(userName);
lifecycleState.setResonForChange(lifecycleChanger.getReason()); lifecycleState.setReasonForChange(lifecycleChanger.getReason());
applicationReleaseDTO.setCurrentState(lifecycleChanger.getAction()); applicationReleaseDTO.setCurrentState(lifecycleChanger.getAction());
if (this.applicationReleaseDAO.updateRelease(applicationReleaseDTO, tenantId) == null) { if (this.applicationReleaseDAO.updateRelease(applicationReleaseDTO, tenantId) == null) {
String msg = "Application release updating is failed/."; String msg = "Application release updating is failed/.";
@ -2251,7 +2152,11 @@ public class ApplicationManagerImpl implements ApplicationManager {
String supportedOSVersions = applicationReleaseWrapper.getSupportedOsVersions(); String supportedOSVersions = applicationReleaseWrapper.getSupportedOsVersions();
if (!StringUtils.isEmpty(supportedOSVersions)) { if (!StringUtils.isEmpty(supportedOSVersions)) {
//todo check OS versions are supported or not if (!isValidOsVersions(supportedOSVersions, deviceType)){
String msg = "You are trying to update application release which has invalid or unsupported OS "
+ "versions in the supportedOsVersions section. Hence, please re-evaluate the request payload.";
log.error(msg);
throw new BadRequestException(msg); }
applicationReleaseDTO.setSupportedOsVersions(supportedOSVersions); applicationReleaseDTO.setSupportedOsVersions(supportedOSVersions);
} }
if (!StringUtils.isEmpty(applicationReleaseWrapper.getDescription())) { if (!StringUtils.isEmpty(applicationReleaseWrapper.getDescription())) {
@ -2451,7 +2356,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
List<CategoryDTO> registeredCategories = this.applicationDAO.getAllCategories(tenantId); List<CategoryDTO> registeredCategories = this.applicationDAO.getAllCategories(tenantId);
if (registeredCategories.isEmpty()) { if (registeredCategories.isEmpty()) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Registered application category set is empty. Since it is mandatory to add application " String msg = "Registered application category set is empty. Since it is mandatory to add application "
+ "category when adding new application, registered application category list shouldn't be null."; + "category when adding new application, registered application category list shouldn't be null.";
log.error(msg); log.error(msg);
@ -2482,7 +2386,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
log.error(msg); log.error(msg);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
} catch (UserStoreException e) { } catch (UserStoreException e) {
ConnectionManagerUtil.rollbackDBTransaction();
String msg = "Error occurred when validating the unrestricted roles given for the web clip"; String msg = "Error occurred when validating the unrestricted roles given for the web clip";
log.error(msg); log.error(msg);
throw new ApplicationManagementException(msg, e); throw new ApplicationManagementException(msg, e);
@ -2551,7 +2454,6 @@ public class ApplicationManagerImpl implements ApplicationManager {
} }
} }
@Override @Override
public void validateImageArtifacts(Attachment iconFile, Attachment bannerFile, public void validateImageArtifacts(Attachment iconFile, Attachment bannerFile,
List<Attachment> attachmentList) throws RequestValidatingException { List<Attachment> attachmentList) throws RequestValidatingException {
@ -2626,10 +2528,14 @@ public class ApplicationManagerImpl implements ApplicationManager {
throw new NotFoundException(msg); throw new NotFoundException(msg);
} }
ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0);
String host = System.getProperty(Constants.IOT_HOST_PROPERTY);
String port = System.getProperty(Constants.IOT_PORT_PROPERTY);
String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration() String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration()
.getArtifactDownloadEndpoint(); .getArtifactDownloadEndpoint();
String artifactDownloadURL = artifactDownloadEndpoint + Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid() String artifactDownloadURL =
+ Constants.FORWARD_SLASH + applicationReleaseDTO.getInstallerName(); Constants.ARTIFACT_DOWNLOAD_PROTOCOL + "://" + host + ":" + port + artifactDownloadEndpoint
+ Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid() + Constants.FORWARD_SLASH
+ applicationReleaseDTO.getInstallerName();
String plistContent = "&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTDPLIST1.0//EN&quot; &quot;" + String plistContent = "&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTDPLIST1.0//EN&quot; &quot;" +
"http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;&lt;plist version=&quot;" + "http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;&lt;plist version=&quot;" +
"1.0&quot;&gt;&lt;dict&gt;&lt;key&gt;items&lt;/key&gt;&lt;array&gt;&lt;dict&gt;&lt;" + "1.0&quot;&gt;&lt;dict&gt;&lt;key&gt;items&lt;/key&gt;&lt;array&gt;&lt;dict&gt;&lt;" +

@ -478,11 +478,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
} }
} else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) { } else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) {
if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) { if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) {
String host = System.getProperty(Constants.IOT_HOST_PROPERTY);
String port = System.getProperty(Constants.IOT_PORT_PROPERTY);
String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration() String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration()
.getArtifactDownloadEndpoint(); .getArtifactDownloadEndpoint();
String plistDownloadEndpoint = artifactDownloadEndpoint + Constants.FORWARD_SLASH + String plistDownloadEndpoint =
MDMAppConstants.IOSConstants.PLIST + Constants.FORWARD_SLASH + Constants.ARTIFACT_DOWNLOAD_PROTOCOL + "://" + host + ":" + port + artifactDownloadEndpoint
application.getApplicationReleases().get(0).getUuid(); + Constants.FORWARD_SLASH + MDMAppConstants.IOSConstants.PLIST
+ Constants.FORWARD_SLASH + application.getApplicationReleases().get(0).getUuid();
mobileApp.setType(mobileAppType); mobileApp.setType(mobileAppType);
mobileApp.setLocation(plistDownloadEndpoint); mobileApp.setLocation(plistDownloadEndpoint);
Properties properties = new Properties(); Properties properties = new Properties();

@ -334,9 +334,12 @@ public class APIUtil {
} }
public static ApplicationRelease releaseDtoToRelease(ApplicationReleaseDTO applicationReleaseDTO){ public static ApplicationRelease releaseDtoToRelease(ApplicationReleaseDTO applicationReleaseDTO){
String host = System.getProperty(Constants.IOT_HOST_PROPERTY);
String port = System.getProperty(Constants.IOT_PORT_PROPERTY);
String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration() String artifactDownloadEndpoint = ConfigurationManager.getInstance().getConfiguration()
.getArtifactDownloadEndpoint(); .getArtifactDownloadEndpoint();
String basePath = artifactDownloadEndpoint + Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid() String basePath = Constants.ARTIFACT_DOWNLOAD_PROTOCOL + "://" + host + ":" + port + artifactDownloadEndpoint
+ Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid()
+ Constants.FORWARD_SLASH; + Constants.FORWARD_SLASH;
List<String> screenshotPaths = new ArrayList<>(); List<String> screenshotPaths = new ArrayList<>();

@ -36,6 +36,9 @@ public class Constants {
public static final String PLIST_NAME = "Info.plist"; public static final String PLIST_NAME = "Info.plist";
public static final String CF_BUNDLE_VERSION = "CFBundleVersion"; public static final String CF_BUNDLE_VERSION = "CFBundleVersion";
public static final String APP_EXTENSION = ".app"; public static final String APP_EXTENSION = ".app";
public static final String IOT_HOST_PROPERTY = "iot.core.host";
public static final String IOT_PORT_PROPERTY = "iot.core.http.port";
public static final String ARTIFACT_DOWNLOAD_PROTOCOL = "http";
public static final String FORWARD_SLASH = "/"; public static final String FORWARD_SLASH = "/";
public static final String ANY = "ANY"; public static final String ANY = "ANY";

@ -22,6 +22,10 @@ import org.wso2.carbon.device.application.mgt.core.dao.common.ApplicationManagem
import org.wso2.carbon.device.application.mgt.core.dto.ApplicationsDTO; import org.wso2.carbon.device.application.mgt.core.dto.ApplicationsDTO;
import org.wso2.carbon.device.application.mgt.core.impl.ApplicationManagerImpl; import org.wso2.carbon.device.application.mgt.core.impl.ApplicationManagerImpl;
import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil; import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.dto.DeviceTypeVersion;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -45,7 +49,7 @@ public class ApplicationManagementTest extends BaseTestCase {
ConnectionManagerUtil.closeDBConnection(); ConnectionManagerUtil.closeDBConnection();
} }
@Test(dependsOnMethods = ("addAplicationCategories")) @Test(dependsOnMethods = ("addApplicationCategories"))
public void createApplication() throws Exception { public void createApplication() throws Exception {
log.debug("Creating the first application ....!"); log.debug("Creating the first application ....!");
@ -75,7 +79,7 @@ public class ApplicationManagementTest extends BaseTestCase {
releaseWrapper.setMetaData("Just meta data"); releaseWrapper.setMetaData("Just meta data");
releaseWrapper.setReleaseType("free"); releaseWrapper.setReleaseType("free");
releaseWrapper.setPrice(5.7); releaseWrapper.setPrice(5.7);
releaseWrapper.setSupportedOsVersions("5.7, 6.1"); releaseWrapper.setSupportedOsVersions("4.0-7.0");
applicationReleaseWrappers.add(releaseWrapper); applicationReleaseWrappers.add(releaseWrapper);
applicationWrapper.setApplicationReleaseWrappers(applicationReleaseWrappers); applicationWrapper.setApplicationReleaseWrappers(applicationReleaseWrappers);
@ -196,9 +200,8 @@ public class ApplicationManagementTest extends BaseTestCase {
} }
@Test @Test(dependsOnMethods = ("addDeviceVersions"))
public void addAplicationCategories() throws ApplicationManagementException { public void addApplicationCategories() throws ApplicationManagementException {
List<String> categories = new ArrayList<>(); List<String> categories = new ArrayList<>();
categories.add("Test Category"); categories.add("Test Category");
categories.add("Test Category2"); categories.add("Test Category2");
@ -207,6 +210,41 @@ public class ApplicationManagementTest extends BaseTestCase {
} }
@Test
public void addDeviceVersions() throws ApplicationManagementException {
List<DeviceTypeVersion> deviceTypeVersions = new ArrayList<>();
List<String> supportingVersions = new ArrayList<>();
//add supporting versions
supportingVersions.add("4.0");
supportingVersions.add("5.0");
supportingVersions.add("6.0");
supportingVersions.add("7.0");
supportingVersions.add("8.0");
DeviceManagementProviderServiceImpl deviceManagementProviderService = new DeviceManagementProviderServiceImpl();
try {
List<DeviceType> deviceTypes = deviceManagementProviderService.getDeviceTypes();
for (DeviceType deviceType: deviceTypes){
for (String version : supportingVersions){
DeviceTypeVersion deviceTypeVersion = new DeviceTypeVersion();
deviceTypeVersion.setDeviceTypeId(deviceType.getId());
deviceTypeVersion.setVersionName(version);
deviceTypeVersions.add(deviceTypeVersion);
}
}
for (DeviceTypeVersion deviceTypeVersion : deviceTypeVersions){
deviceManagementProviderService.addDeviceTypeVersion(deviceTypeVersion);
}
} catch (DeviceManagementException e) {
String msg = "Error Occured while adding device type versions";
log.error(msg);
throw new ApplicationManagementException(msg);
}
}
@Test @Test
public List<Tag> getRegisteredTags() throws ApplicationManagementException { public List<Tag> getRegisteredTags() throws ApplicationManagementException {
return null; return null;

@ -1,155 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>3.2.7-SNAPSHOT</version>
</parent>
<artifactId>org.wso2.carbon.device.application.mgt.handler</artifactId>
<version>3.2.7-SNAPSHOT</version>
<packaging>war</packaging>
<name>WSO2 Carbon - Application Management Authentication Handler API</name>
<description>Proxy Service for Authentication Handling in WSO2 App Manager.</description>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*cxf*.jar</packagingExcludes>
<warName>api#application-mgt-handler#v1.0</warName>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>deploy</id>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy todir="${basedir}/../../../repository/deployment/server/webapps" overwrite="true">
<fileset dir="${basedir}/target">
<include name="api#application-mgt-handler#v1.0.war" />
</fileset>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>client</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.application.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.application.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -1,239 +0,0 @@
/* 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.device.application.mgt.handler;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.wso2.carbon.device.application.mgt.common.ProxyResponse;
import org.wso2.carbon.device.application.mgt.handler.beans.AuthData;
import org.wso2.carbon.device.application.mgt.handler.util.HandlerConstants;
import org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute;
@MultipartConfig
@WebServlet("/invoke")
public class InvokerHandler extends HttpServlet {
private static final Log log = LogFactory.getLog(LoginHandler.class);
private static final long serialVersionUID = -6508020875358160165L;
private static AuthData authData;
private static String apiEndpoint;
private static String method;
private static String serverUrl;
private static String platform;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
try {
if (!validateRequest(req, resp)) {
return;
}
HttpRequestBase executor = constructExecutor(req);
if (executor == null) {
resp.sendError(HTTP_BAD_REQUEST, "Bad Request, method: " + method + " is not supported");
return;
}
executor.setHeader(HandlerConstants.AUTHORIZATION_HEADER_KEY, "Bearer " + authData.getAccessToken());
ProxyResponse proxyResponse = execute(executor);
if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) {
if (!refreshToken(req, resp)) {
return;
}
executor.setHeader(HandlerConstants.AUTHORIZATION_HEADER_KEY, "Bearer " + authData.getAccessToken());
proxyResponse = execute(executor);
if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while invoking the API after refreshing the token.");
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return;
}
}
if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while invoking the API endpoint.");
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return;
}
HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse);
} catch (IOException e) {
log.error("Error occured when processing invoke call.", e);
}
}
/***
*
* @param req {@link HttpServletRequest}
* @return {@link HttpRequestBase} if method equals to either GET, POST, PUT or DELETE otherwise returns NULL.
*/
private HttpRequestBase constructExecutor(HttpServletRequest req) {
String payload = req.getParameter("payload");
String contentType = req.getParameter("content-type");
if (contentType == null || contentType.isEmpty()) {
contentType = ContentType.APPLICATION_JSON.toString();
}
HttpRequestBase executor;
if (HttpGet.METHOD_NAME.equalsIgnoreCase(method)) {
executor = new HttpGet(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint);
} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(method)) {
executor = new HttpPost(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint);
StringEntity payloadEntity = new StringEntity(payload, ContentType.create(contentType));
((HttpPost) executor).setEntity(payloadEntity);
} else if (HttpPut.METHOD_NAME.equalsIgnoreCase(method)) {
executor = new HttpPut(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint);
StringEntity payloadEntity = new StringEntity(payload, ContentType.create(contentType));
((HttpPut) executor).setEntity(payloadEntity);
} else if (HttpDelete.METHOD_NAME.equalsIgnoreCase(method)) {
executor = new HttpDelete(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint);
} else {
return null;
}
return executor;
}
/***
*
* @param req {@link HttpServletRequest}
* @param resp {@link HttpServletResponse}
* @return If request is a valid one, returns TRUE, otherwise return FALSE
* @throws IOException If and error occurs while witting error response to client side
*/
private static boolean validateRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
apiEndpoint = req.getParameter("api-endpoint");
method = req.getParameter("method");
HttpSession session = req.getSession(false);
if (session == null) {
log.error("Unauthorized, You are not logged in. Please log in to the portal");
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false;
}
authData = (AuthData) session.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY);
platform = (String) session.getAttribute(HandlerConstants.PLATFORM);
if (authData == null) {
log.error("Unauthorized, Access token couldn't found in the current session");
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false;
}
if (apiEndpoint == null || method == null) {
log.error("Bad Request, Either api-endpoint or method is empty");
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_BAD_REQUEST);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_BAD_REQUEST));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false;
}
return true;
}
/***
*
* @param req {@link HttpServletRequest}
* @param resp {@link HttpServletResponse}
* @return If successfully renew tokens, returns TRUE otherwise return FALSE
* @throws IOException If and error occurs while witting error response to client side or invoke token renewal API
*/
private static boolean refreshToken(HttpServletRequest req, HttpServletResponse resp) throws IOException {
log.debug("refreshing the token");
HttpPost tokenEndpoint = new HttpPost(
serverUrl + HandlerConstants.API_COMMON_CONTEXT + HandlerConstants.TOKEN_ENDPOINT);
HttpSession session = req.getSession(false);
if (session == null) {
log.error("Couldn't find a session, hence it is required to login and proceed.");
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false;
}
StringEntity tokenEndpointPayload = new StringEntity(
"grant_type=refresh_token&refresh_token=" + authData.getRefreshToken() + "&scope=PRODUCTION",
ContentType.APPLICATION_FORM_URLENCODED);
tokenEndpoint.setEntity(tokenEndpointPayload);
String encodedClientApp = authData.getEncodedClientApp();
tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp);
tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString());
ProxyResponse tokenResultResponse = execute(tokenEndpoint);
if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while refreshing access token.");
HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse);
return false;
}
JsonParser jsonParser = new JsonParser();
JsonElement jTokenResult = jsonParser.parse(tokenResultResponse.getData());
if (jTokenResult.isJsonObject()) {
JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject();
AuthData newAuthData = new AuthData();
newAuthData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString());
newAuthData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString());
newAuthData.setScope(jTokenResultAsJsonObject.get("scope").getAsString());
newAuthData.setClientId(authData.getClientId());
newAuthData.setClientSecret(authData.getClientSecret());
newAuthData.setEncodedClientApp(authData.getEncodedClientApp());
newAuthData.setUsername(authData.getUsername());
authData = newAuthData;
session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, newAuthData);
return true;
}
log.error("Error Occurred in token renewal process.");
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_INTERNAL_SERVER_ERROR));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false;
}
}

@ -1,293 +0,0 @@
/* 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.device.application.mgt.handler;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HTTP;
import org.wso2.carbon.device.application.mgt.common.ProxyResponse;
import org.wso2.carbon.device.application.mgt.handler.beans.AuthData;
import org.wso2.carbon.device.application.mgt.handler.exceptions.LoginException;
import org.wso2.carbon.device.application.mgt.handler.util.HandlerConstants;
import org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Base64;
import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute;
@MultipartConfig
@WebServlet("/login")
public class LoginHandler extends HttpServlet {
private static final Log log = LogFactory.getLog(LoginHandler.class);
private static final long serialVersionUID = 9050048549140517002L;
private static String username;
private static String password;
private static String platform;
private static String serverUrl;
private static String uiConfigUrl;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
try {
validateLoginRequest(req, resp);
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance()
.getDeviceManagementConfig();
String adminUsername = deviceManagementConfig.getIdentityConfigurations().getAdminUsername();
String adminPwd = deviceManagementConfig.getIdentityConfigurations().getAdminPassword();
HttpSession httpSession = req.getSession(false);
if (httpSession != null) {
httpSession.invalidate();
}
httpSession = req.getSession(true);
//setting session to expiry in 5 mins
httpSession.setMaxInactiveInterval(Math.toIntExact(HandlerConstants.TIMEOUT));
HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl);
JsonParser jsonParser = new JsonParser();
ProxyResponse uiConfigResponse = execute(uiConfigEndpoint);
String executorResponse = uiConfigResponse.getExecutorResponse();
if (!StringUtils.isEmpty(executorResponse) && executorResponse
.contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while getting UI configurations by invoking " + uiConfigUrl);
HandlerUtil.handleError(req, resp, serverUrl, platform, uiConfigResponse);
return;
}
String uiConfig = uiConfigResponse.getData();
if (uiConfig == null){
log.error("UI config retrieval is failed, and didn't find UI configuration for App manager.");
HandlerUtil.handleError(req, resp, serverUrl, platform, null);
return;
}
JsonElement uiConfigJsonElement = jsonParser.parse(uiConfigResponse.getData());
JsonObject uiConfigJsonObject = null;
if (uiConfigJsonElement.isJsonObject()) {
uiConfigJsonObject = uiConfigJsonElement.getAsJsonObject();
httpSession.setAttribute(HandlerConstants.UI_CONFIG_KEY, uiConfigJsonObject);
httpSession.setAttribute(HandlerConstants.PLATFORM, serverUrl);
}
if (uiConfigJsonObject == null) {
log.error(
"Either UI config json element is not an json object or converting rom json element to json object is failed.");
HandlerUtil.handleError(req, resp, serverUrl, platform, null);
return;
}
boolean isSsoEnable = uiConfigJsonObject.get("isSsoEnable").getAsBoolean();
JsonArray tags = uiConfigJsonObject.get("appRegistration").getAsJsonObject().get("tags").getAsJsonArray();
JsonArray scopes = uiConfigJsonObject.get("scopes").getAsJsonArray();
if (isSsoEnable) {
log.debug("SSO is enabled");
} else {
// default login
HttpPost apiRegEndpoint = new HttpPost(serverUrl + HandlerConstants.APP_REG_ENDPOINT);
apiRegEndpoint.setHeader(HandlerConstants.AUTHORIZATION, HandlerConstants.BASIC + Base64.getEncoder()
.encodeToString((adminUsername + HandlerConstants.COLON + adminPwd).getBytes()));
apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
apiRegEndpoint.setEntity(constructAppRegPayload(tags));
ProxyResponse clientAppResponse = execute(apiRegEndpoint);
String clientAppResult = clientAppResponse.getData();
if (!StringUtils.isEmpty(clientAppResult) && getTokenAndPersistInSession(req, resp,
clientAppResponse.getData(), scopes)) {
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_OK);
proxyResponse.setUrl(serverUrl + "/" + platform + uiConfigJsonObject.get(HandlerConstants.LOGIN_RESPONSE_KEY)
.getAsJsonObject().get("successCallback").getAsString());
HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse);
return;
}
HandlerUtil.handleError(req, resp, serverUrl, platform, null);
}
} catch (IOException e) {
log.error("Error occured while sending the response into the socket. ", e);
} catch (JsonSyntaxException e) {
log.error("Error occured while parsing the response. ", e);
} catch (LoginException e) {
log.error("Error occured while getting token data. ", e);
}
}
/***
*
* @param req - {@link HttpServletRequest}
* @param clientAppResult - clientAppResult
* @param scopes - scopes defied in the application-mgt.xml
* @throws LoginException - login exception throws when getting token result
*/
private boolean getTokenAndPersistInSession(HttpServletRequest req, HttpServletResponse resp,
String clientAppResult, JsonArray scopes) throws LoginException {
JsonParser jsonParser = new JsonParser();
try {
JsonElement jClientAppResult = jsonParser.parse(clientAppResult);
if (jClientAppResult.isJsonObject()) {
JsonObject jClientAppResultAsJsonObject = jClientAppResult.getAsJsonObject();
String clientId = jClientAppResultAsJsonObject.get("client_id").getAsString();
String clientSecret = jClientAppResultAsJsonObject.get("client_secret").getAsString();
String encodedClientApp = Base64.getEncoder()
.encodeToString((clientId + ":" + clientSecret).getBytes());
ProxyResponse tokenResultResponse = getTokenResult(encodedClientApp, scopes);
if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while invoking the API to get token data.");
HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse);
return false;
}
String tokenResult = tokenResultResponse.getData();
if (tokenResult == null){
log.error("Invalid token response is received.");
HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse);
return false;
}
JsonElement jTokenResult = jsonParser.parse(tokenResult);
if (jTokenResult.isJsonObject()) {
JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject();
HttpSession session = req.getSession(false);
if (session == null) {
return false;
}
AuthData authData = new AuthData();
authData.setClientId(clientId);
authData.setClientSecret(clientSecret);
authData.setEncodedClientApp(encodedClientApp);
authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString());
authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString());
authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString());
session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData);
return true;
}
}
return false;
} catch (IOException e) {
throw new LoginException("Error occured while sending the response into the socket", e);
}
}
/***
*
* @param scopes - scope Json Array and it is retrieved by reading UI config.
* @return string value of the defined scopes
*/
private String getScopeString(JsonArray scopes) {
if (scopes != null && scopes.size() > 0) {
StringBuilder builder = new StringBuilder();
for (JsonElement scope : scopes) {
String tmpscope = scope.getAsString() + " ";
builder.append(tmpscope);
}
return builder.toString();
} else {
return null;
}
}
/***
*
* @param req - {@link HttpServletRequest}
* Define username and password static parameters.
*/
private static void validateLoginRequest(HttpServletRequest req, HttpServletResponse resp) throws LoginException {
username = req.getParameter("username");
password = req.getParameter("password");
platform = req.getParameter("platform");
serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
uiConfigUrl = serverUrl + HandlerConstants.UI_CONFIG_ENDPOINT;
try {
if (platform == null) {
resp.sendRedirect(serverUrl + HandlerConstants.DEFAULT_ERROR_CALLBACK);
throw new LoginException("Invalid login request. Platform parameter is Null.");
}
if (username == null || password == null) {
resp.sendRedirect(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK);
throw new LoginException(
" Invalid login request. Username or Password is not received for login request.");
}
} catch (IOException e) {
throw new LoginException("Error Occured while redirecting to default error page.", e);
}
}
/***
*
* @param tags - tags which are retrieved by reading app manager configuration
* @return {@link StringEntity} of the payload to create the client application
*/
private StringEntity constructAppRegPayload(JsonArray tags) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(HandlerConstants.APP_NAME_KEY, HandlerConstants.PUBLISHER_APPLICATION_NAME);
jsonObject.addProperty("isAllowedToAllDomains", "false");
jsonObject.add(HandlerConstants.TAGS_KEY, tags);
String payload = jsonObject.toString();
return new StringEntity(payload, ContentType.APPLICATION_JSON);
}
/***
*
* @param encodedClientApp - Base64 encoded clientId:clientSecret.
* @param scopes - Scopes which are retrieved by reading application-mgt configuration
* @return Invoke token endpoint and return the response as string.
* @throws IOException IO exception throws if an error occured when invoking token endpoint
*/
private ProxyResponse getTokenResult(String encodedClientApp, JsonArray scopes) throws IOException {
HttpPost tokenEndpoint = new HttpPost(serverUrl + HandlerConstants.TOKEN_ENDPOINT);
tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp);
tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString());
String scopeString = getScopeString(scopes);
if (scopeString != null) {
scopeString = scopeString.trim();
} else {
scopeString = "default";
}
StringEntity tokenEPPayload = new StringEntity(
"grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString,
ContentType.APPLICATION_FORM_URLENCODED);
tokenEndpoint.setEntity(tokenEPPayload);
return execute(tokenEndpoint);
}
}

@ -1,88 +0,0 @@
/* 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.handler.beans;
public class AuthData implements java.io.Serializable {
private static final long serialVersionUID = -5156750882531944849L;
private String accessToken;
private String refreshToken;
private String username;
private String clientId;
private String clientSecret;
private String encodedClientApp;
private String scope;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public String getEncodedClientApp() {
return encodedClientApp;
}
public void setEncodedClientApp(String encodedClientApp) {
this.encodedClientApp = encodedClientApp;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}

@ -1,38 +0,0 @@
/* 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.device.application.mgt.handler.exceptions;
public class LoginException extends Exception {
public LoginException(String message) {
super(message);
}
public LoginException(String message, Throwable cause) {
super(message, cause);
}
public LoginException(Throwable cause) {
super(cause);
}
public LoginException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

@ -1,44 +0,0 @@
/* 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.device.application.mgt.handler.util;
public class HandlerConstants {
public static final String PUBLISHER_APPLICATION_NAME = "application-mgt-publisher";
public static final String APP_REG_ENDPOINT = "/api-application-registration/register";
public static final String UI_CONFIG_ENDPOINT = "/api/application-mgt/v1.0/config/ui-config";
public static final String TOKEN_ENDPOINT = "/oauth2/token";
public static final String AUTHORIZATION = "Authorization";
public static final String BASIC = "Basic ";
public static final String COLON = ":";
public static final String TAGS_KEY = "tags";
public static final String APP_NAME_KEY = "applicationName";
public static final String SESSION_AUTH_DATA_KEY = "application-mgt";
public static final String AUTHORIZATION_HEADER_KEY = "Authorization";
public static final String UI_CONFIG_KEY = "ui-config";
public static final String PLATFORM = "platform";
public static final String SERVER_HOST = "server-host";
public static final String DEFAULT_ERROR_CALLBACK = "/pages/error/default";
public static final String LOGIN_RESPONSE_KEY = "loginResponse";
public static final String FAILURE_CALLBACK_KEY = "failureCallback";
public static final String API_COMMON_CONTEXT = "/api";
public static final String EXECUTOR_EXCEPTION_PREFIX = "ExecutorException-";
public static final String TOKEN_IS_EXPIRED = "ACCESS_TOKEN_IS_EXPIRED";
public static final int INTERNAL_ERROR_CODE = 500;
public static final long TIMEOUT = 1200;
}

@ -1,241 +0,0 @@
/* 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.handler.util;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.carbon.device.application.mgt.common.ProxyResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class HandlerUtil {
private static final Log log = LogFactory.getLog(HandlerUtil.class);
/***
*
* @param httpMethod - httpMethod e.g:- HttpPost, HttpGet
* @param <T> - HttpPost or HttpGet class
* @return response as string
* @throws IOException IO exception returns if error occurs when executing the httpMethod
*/
public static <T> ProxyResponse execute(T httpMethod) throws IOException {
try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpResponse response = null;
if (httpMethod instanceof HttpPost) {
HttpPost method = (HttpPost) httpMethod;
response = client.execute(method);
} else if (httpMethod instanceof HttpGet) {
HttpGet method = (HttpGet) httpMethod;
response = client.execute(method);
} else if (httpMethod instanceof HttpPut) {
HttpPut method = (HttpPut) httpMethod;
response = client.execute(method);
} else if (httpMethod instanceof HttpDelete) {
HttpDelete method = (HttpDelete) httpMethod;
response = client.execute(method);
}
ProxyResponse proxyResponse = new ProxyResponse();
if (response == null) {
proxyResponse.setCode(HandlerConstants.INTERNAL_ERROR_CODE);
proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(
HandlerConstants.INTERNAL_ERROR_CODE));
return proxyResponse;
} else {
int statusCode = response.getStatusLine().getStatusCode();
try (BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
StringBuilder result = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
String jsonString = result.toString();
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) {
proxyResponse.setCode(statusCode);
proxyResponse.setData(jsonString);
proxyResponse.setExecutorResponse("SUCCESS");
return proxyResponse;
} else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
if (jsonString.contains("Access token expired") || jsonString
.contains("Invalid input. Access token validation failed")) {
proxyResponse.setCode(statusCode);
proxyResponse.setExecutorResponse("ACCESS_TOKEN_IS_EXPIRED");
return proxyResponse;
} else {
proxyResponse.setCode(statusCode);
proxyResponse.setData(jsonString);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode));
return proxyResponse;
}
}
proxyResponse.setCode(statusCode);
proxyResponse.setData(jsonString);
proxyResponse
.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode));
return proxyResponse;
}
}
}
}
/***
*
* @param statusCode Provide status code, e.g:- 400, 401, 500 etc
* @return relative status code key for given status code.
*/
public static String getStatusKey (int statusCode){
String statusCodeKey;
switch (statusCode) {
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
statusCodeKey = "internalServerError";
break;
case HttpStatus.SC_BAD_REQUEST:
statusCodeKey = "badRequest";
break;
case HttpStatus.SC_UNAUTHORIZED:
statusCodeKey = "unauthorized";
break;
case HttpStatus.SC_FORBIDDEN:
statusCodeKey = "forbidden";
break;
case HttpStatus.SC_NOT_FOUND:
statusCodeKey = "notFound";
break;
case HttpStatus.SC_METHOD_NOT_ALLOWED:
statusCodeKey = "methodNotAllowed";
break;
case HttpStatus.SC_NOT_ACCEPTABLE:
statusCodeKey = "notAcceptable";
break;
case HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE:
statusCodeKey = "unsupportedMediaType";
break;
default:
statusCodeKey = "defaultPage";
break;
}
return statusCodeKey;
}
/***
*
* @param resp {@link HttpServletResponse}
* Return Error Response.
*/
public static void handleError(HttpServletRequest req, HttpServletResponse resp, String serverUrl,
String platform, ProxyResponse proxyResponse) throws IOException {
HttpSession httpSession = req.getSession(true);
Gson gson = new Gson();
if (proxyResponse == null){
proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil
.getStatusKey(HandlerConstants.INTERNAL_ERROR_CODE));
}
if (platform == null){
platform = "default";
}
resp.setStatus(proxyResponse.getCode());
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
if (httpSession != null) {
JsonObject uiConfig = (JsonObject) httpSession.getAttribute(HandlerConstants.UI_CONFIG_KEY);
if (uiConfig == null){
proxyResponse.setUrl(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK);
} else{
proxyResponse.setUrl(serverUrl + uiConfig.get(HandlerConstants.LOGIN_RESPONSE_KEY).getAsJsonObject()
.get(HandlerConstants.FAILURE_CALLBACK_KEY).getAsJsonObject()
.get(proxyResponse.getExecutorResponse().split(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)[1])
.getAsString());
}
} else {
proxyResponse.setUrl(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK);
}
proxyResponse.setExecutorResponse(null);
try (PrintWriter writer = resp.getWriter()) {
writer.write(gson.toJson(proxyResponse));
}
}
/***
*
* @param resp {@link HttpServletResponse}
* Return Success Response.
*/
public static void handleSuccess(HttpServletRequest req, HttpServletResponse resp, String serverUrl,
String platform, ProxyResponse proxyResponse) throws IOException {
if (proxyResponse == null){
handleError(req,resp,serverUrl,platform,proxyResponse);
return;
}
resp.setStatus(proxyResponse.getCode());
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
JSONObject response = new JSONObject();
String redirectUrl = proxyResponse.getUrl();
String responseData = proxyResponse.getData();
if (!StringUtils.isEmpty(redirectUrl)){
response.put("url", redirectUrl);
}
if (!StringUtils.isEmpty(responseData)){
try {
JSONObject responseDataJsonObj = new JSONObject(responseData);
response.put("data", responseDataJsonObj);
} catch (JSONException e) {
log.debug("Response data is not valid json string");
response.put("data", responseData);
}
}
try (PrintWriter writer = resp.getWriter()) {
writer.write(response.toString());
}
}
}

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
* 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>Carbon</Environments>
</Classloading>

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Application Management Auth Webapp</display-name>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,DELETE,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type</param-value>
</init-param>
</filter>
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -273,7 +273,7 @@ public interface ApplicationManagementPublisherAPI {
@POST @POST
@Path("/ent-app") @Path("/ent-app")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@ApiOperation( @ApiOperation(
consumes = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -342,7 +342,7 @@ public interface ApplicationManagementPublisherAPI {
@POST @POST
@Path("/web-app") @Path("/web-app")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@ApiOperation( @ApiOperation(
consumes = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -406,7 +406,7 @@ public interface ApplicationManagementPublisherAPI {
@POST @POST
@Path("/public-app") @Path("/public-app")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@ApiOperation( @ApiOperation(
consumes = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -467,7 +467,7 @@ public interface ApplicationManagementPublisherAPI {
@POST @POST
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Path("/ent-app/{appId}") @Path("/ent-app/{appId}")
@ApiOperation( @ApiOperation(
consumes = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON,
@ -583,7 +583,7 @@ public interface ApplicationManagementPublisherAPI {
@PUT @PUT
@Path("/image-artifacts/{uuid}") @Path("/image-artifacts/{uuid}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@ApiOperation( @ApiOperation(
consumes = MediaType.MULTIPART_FORM_DATA, consumes = MediaType.MULTIPART_FORM_DATA,
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -653,7 +653,7 @@ public interface ApplicationManagementPublisherAPI {
@PUT @PUT
@Path("/app-artifacts/{deviceType}/{appType}/{appId}/{uuid}") @Path("/app-artifacts/{deviceType}/{appType}/{appId}/{uuid}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@ApiOperation( @ApiOperation(
consumes = MediaType.MULTIPART_FORM_DATA, consumes = MediaType.MULTIPART_FORM_DATA,
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,

@ -0,0 +1,313 @@
/* 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.publisher.api.services.admin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.application.mgt.common.ErrorResponse;
import org.wso2.carbon.device.application.mgt.common.PaginationResult;
import org.wso2.carbon.device.application.mgt.common.response.Review;
import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
/**
* APIs to handle admin review management related tasks in publisher.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "Publisher Review Management Admin Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "PublisherReviewManagementAdminService"),
@ExtensionProperty(name = "context", value = "/api/application-mgt/v1.0/admin/review"),
})
}
),
tags = {
@Tag(name = "review_management", description = "Publisher Review Management related Admin APIs")
}
)
@Scopes(
scopes = {
@Scope(
name = "Update a Review",
description = "Update a Review of applications.",
key = "perm:admin:app:review:update",
permissions = {"/app-mgt/publisher/admin/review/update"}
),
@Scope(
name = "Get Review Details",
description = "Get review details of applications.",
key = "perm:admin:app:review:view",
permissions = {"/app-mgt/publisher/admin/review/view"}
)
}
)
@Path("/admin/reviews")
@Api(value = "Publisher Review Management Admin API")
@Produces(MediaType.APPLICATION_JSON)
public interface ReviewManagementAdminAPI {
String SCOPE = "scope";
@PUT
@Path("/{uuid}/{reviewId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "PUT",
value = "Edit a review",
notes = "This will edit the review",
tags = "Review Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:update")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully updated reviewTmp.",
response = Review.class),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while updating the new reviewTmp.",
response = ErrorResponse.class)
})
Response updateReview(
@ApiParam(
name = "reviewTmp",
value = "The review that need to be updated.",
required = true)
@Valid ReviewWrapper updatingReview,
@ApiParam(
name = "uuid",
value = "uuid of the application release",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(
name = "reviewId",
value = "review id of the updating reviewTmp.",
required = true)
@PathParam("reviewId") int reviewId);
@DELETE
@Path("/{uuid}/{reviewId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "DELETE",
value = "Remove review",
notes = "Remove review",
tags = "Review Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:update")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deleted the review"),
@ApiResponse(
code = 404,
message = "Not Found. \n No activity found with the given ID.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while deleting the review.",
response = ErrorResponse.class)
})
Response deleteReview(
@ApiParam(
name = "uuid",
value = "UUID of the application release.",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(
name = "reviewId",
value = "Id of the review.",
required = true)
@PathParam("reviewId") int reviewId);
@GET
@Path("/release/{uuid}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "get app release reviews",
notes = "Get all app release reviews",
tags = "Review Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved app release reviews.",
response = PaginationResult.class,
responseContainer = "PaginationResult"),
@ApiResponse(
code = 404,
message = "Not Found. \n Not found an application release for requested UUID."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting the review list.",
response = ErrorResponse.class)
})
Response getAllReleaseReviews(
@ApiParam(
name = "uuid",
value = "uuid of the application release.",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(
name = "offset",
value = "Starting review number.",
defaultValue = "0")
@QueryParam("offSet") int offSet,
@ApiParam(
name = "limit",
value = "Limit of paginated reviews",
defaultValue = "20")
@QueryParam("limit") int limit);
@GET
@Path("/{uuid}/release-rating")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "get ratings",
notes = "Get all ratings",
tags = "Review Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved ratings.",
response = List.class,
responseContainer = "List"),
@ApiResponse(
code = 404,
message = "Not Found. \n No Application release found for application release UUID.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting ratings",
response = ErrorResponse.class)
})
Response getAppReleaseRating(
@ApiParam(
name = "uuid",
value = "uuid of the application release",
required = true)
@PathParam("uuid") String uuid);
@GET
@Path("/{uuid}/app-rating")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "get app ratings",
notes = "Get all app ratings",
tags = "Store Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved ratings.",
response = List.class,
responseContainer = "List"),
@ApiResponse(
code = 404,
message = "Not Found. \n No Application found which has application release of UUID.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting ratings",
response = ErrorResponse.class)
})
Response getAppRating(
@ApiParam(
name = "uuid",
value = "uuid of the application release",
required = true)
@PathParam("uuid")
String uuid);
}

@ -164,7 +164,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
} }
@POST @POST
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Path("/ent-app") @Path("/ent-app")
public Response createEntApp( public Response createEntApp(
@Multipart("application") ApplicationWrapper applicationWrapper, @Multipart("application") ApplicationWrapper applicationWrapper,
@ -204,7 +204,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
} }
@POST @POST
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Path("/web-app") @Path("/web-app")
public Response createWebApp( public Response createWebApp(
@Multipart("webapp") WebAppWrapper webAppWrapper, @Multipart("webapp") WebAppWrapper webAppWrapper,
@ -242,7 +242,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
} }
@POST @POST
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Path("/public-app") @Path("/public-app")
public Response createPubApp( public Response createPubApp(
@Multipart("public-app") PublicAppWrapper publicAppWrapper, @Multipart("public-app") PublicAppWrapper publicAppWrapper,
@ -280,7 +280,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
} }
@POST @POST
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Path("/ent-app/{appId}") @Path("/ent-app/{appId}")
public Response createEntAppRelease( public Response createEntAppRelease(
@PathParam("appId") int appId, @PathParam("appId") int appId,
@ -320,7 +320,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
@Override @Override
@PUT @PUT
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Path("/image-artifacts/{uuid}") @Path("/image-artifacts/{uuid}")
public Response updateApplicationImageArtifacts( public Response updateApplicationImageArtifacts(
@ -357,7 +357,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
@Override @Override
@PUT @PUT
@Consumes("multipart/mixed") @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA})
@Path("/app-artifact/{deviceType}/{appType}/{uuid}") @Path("/app-artifact/{deviceType}/{appType}/{uuid}")
public Response updateApplicationArtifact( public Response updateApplicationArtifact(
@PathParam("deviceType") String deviceType, @PathParam("deviceType") String deviceType,
@ -367,9 +367,8 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem
try { try {
if (!ApplicationType.ENTERPRISE.toString().equals(appType)) { if (!ApplicationType.ENTERPRISE.toString().equals(appType)) {
String msg = "If ApplicationDTO type is " + appType String msg = "If Application type is " + appType + ", then you don't have application release artifact "
+ ", therefore you don't have application release artifact to update for application release UUID: " + "to update for application release UUID: " + applicationReleaseUuid;
+ applicationReleaseUuid;
log.error(msg); log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} }

@ -14,24 +14,30 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.wso2.carbon.device.application.mgt.store.api.services.impl.admin; package org.wso2.carbon.device.application.mgt.publisher.api.services.impl.admin;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.common.PaginationRequest;
import org.wso2.carbon.device.application.mgt.common.PaginationResult;
import org.wso2.carbon.device.application.mgt.common.Rating;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.exception.ReviewManagementException; import org.wso2.carbon.device.application.mgt.common.exception.ReviewManagementException;
import org.wso2.carbon.device.application.mgt.common.services.ReviewManager; import org.wso2.carbon.device.application.mgt.common.services.ReviewManager;
import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper; import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper;
import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException; import org.wso2.carbon.device.application.mgt.core.exception.NotFoundException;
import org.wso2.carbon.device.application.mgt.core.util.APIUtil; import org.wso2.carbon.device.application.mgt.core.util.APIUtil;
import org.wso2.carbon.device.application.mgt.store.api.services.admin.ReviewManagementAdminAPI; import org.wso2.carbon.device.application.mgt.publisher.api.services.admin.ReviewManagementAdminAPI;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
/** /**
@ -99,4 +105,73 @@ public class ReviewManagementAdminAPIImpl implements ReviewManagementAdminAPI {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} }
} }
@Override
@GET
@Path("/release/{uuid}")
public Response getAllReleaseReviews(
@PathParam("uuid") String uuid,
@DefaultValue("0") @QueryParam("offset") int offSet,
@DefaultValue("20") @QueryParam("limit") int limit) {
ReviewManager reviewManager = APIUtil.getReviewManager();
PaginationRequest request = new PaginationRequest(offSet, limit);
try {
PaginationResult paginationResult = reviewManager.getAllReleaseReviews(request, uuid);
return Response.status(Response.Status.OK).entity(paginationResult).build();
} catch (NotFoundException e) {
String msg = "Couldn't find an application release for UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (ReviewManagementException e) {
String msg = "Error occurred while retrieving reviews for application UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (ApplicationManagementException e) {
String msg = "Error occurred while retrieving application release details for application UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
@Override
@GET
@Path("/{uuid}/release-rating")
public Response getAppReleaseRating(
@PathParam("uuid") String uuid) {
ReviewManager reviewManager = APIUtil.getReviewManager();
Rating rating;
try {
rating = reviewManager.getAppReleaseRating(uuid);
} catch (NotFoundException e) {
String msg = "Couldn't found an application release for UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (ReviewManagementException | ApplicationManagementException e) {
String msg = "Error occured while getting review data for application release UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.OK).entity(rating).build();
}
@Override
@GET
@Path("/{uuid}/app-rating")
public Response getAppRating(
@PathParam("uuid") String uuid) {
ReviewManager reviewManager = APIUtil.getReviewManager();
Rating rating;
try {
rating = reviewManager.getAppRating(uuid);
} catch (NotFoundException e) {
String msg = "Couldn't found an application for application release UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (ReviewManagementException | ApplicationManagementException e) {
String msg = "Error occured while getting review data for application release UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.OK).entity(rating).build();
}
} }

@ -26,6 +26,7 @@
<jaxrs:server id="applicationMgtService" address="/"> <jaxrs:server id="applicationMgtService" address="/">
<jaxrs:serviceBeans> <jaxrs:serviceBeans>
<ref bean="applicationMgtServiceBean"/> <ref bean="applicationMgtServiceBean"/>
<ref bean="reviewMgtAdminServiceBean"/>
<ref bean="applicationMgtAdminServiceBean"/> <ref bean="applicationMgtAdminServiceBean"/>
<ref bean="swaggerResource"/> <ref bean="swaggerResource"/>
</jaxrs:serviceBeans> </jaxrs:serviceBeans>
@ -55,6 +56,7 @@
<bean id="applicationMgtServiceBean" class="org.wso2.carbon.device.application.mgt.publisher.api.services.impl.ApplicationManagementPublisherAPIImpl"/> <bean id="applicationMgtServiceBean" class="org.wso2.carbon.device.application.mgt.publisher.api.services.impl.ApplicationManagementPublisherAPIImpl"/>
<bean id="applicationMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.publisher.api.services.impl.admin.ApplicationManagementPublisherAdminAPIImpl"/> <bean id="applicationMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.publisher.api.services.impl.admin.ApplicationManagementPublisherAdminAPIImpl"/>
<bean id="reviewMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.publisher.api.services.impl.admin.ReviewManagementAdminAPIImpl" />
<bean id="jsonProvider" class="org.wso2.carbon.device.application.mgt.addons.JSONMessageHandler"/> <bean id="jsonProvider" class="org.wso2.carbon.device.application.mgt.addons.JSONMessageHandler"/>
<bean id="multipartProvider" class="org.wso2.carbon.device.application.mgt.addons.MultipartCustomProvider"/> <bean id="multipartProvider" class="org.wso2.carbon.device.application.mgt.addons.MultipartCustomProvider"/>

@ -49,9 +49,9 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.List; import java.util.List;
/** /**
* APIs to handle review management related tasks. * APIs to handle review management related tasks.
*/ */
@SwaggerDefinition( @SwaggerDefinition(
info = @Info( info = @Info(
@ -60,7 +60,7 @@ import java.util.List;
extensions = { extensions = {
@Extension(properties = { @Extension(properties = {
@ExtensionProperty(name = "name", value = "ReviewManagementService"), @ExtensionProperty(name = "name", value = "ReviewManagementService"),
@ExtensionProperty(name = "context", value = "/api/application-mgt/v1.0/review"), @ExtensionProperty(name = "context", value = "/api/application-mgt/v1.0/store/review"),
}) })
} }
), ),
@ -92,13 +92,13 @@ public interface ReviewManagementAPI {
String SCOPE = "scope"; String SCOPE = "scope";
@GET @GET
@Path("/release/{uuid}") @Path("/app/user/{uuid}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "GET", httpMethod = "GET",
value = "get app release reviews", value = "get app reviews",
notes = "Get all app release reviews", notes = "Get all app reviews",
tags = "Store Management", tags = "Store Management",
extensions = { extensions = {
@Extension(properties = { @Extension(properties = {
@ -111,19 +111,20 @@ public interface ReviewManagementAPI {
value = { value = {
@ApiResponse( @ApiResponse(
code = 200, code = 200,
message = "OK. \n Successfully retrieved app release reviews.", message = "OK. \n Successfully retrieved app reviews.",
response = PaginationResult.class, response = PaginationResult.class,
responseContainer = "PaginationResult"), responseContainer = "PaginationResult"),
@ApiResponse( @ApiResponse(
code = 404, code = 404,
message = "Not Found. \n Not found an application release for requested UUID."), message = "Not Found. \n Not found an application release associated with requested "
+ "UUID."),
@ApiResponse( @ApiResponse(
code = 500, code = 500,
message = "Internal Server Error. \n Error occurred while getting the review list.", message = "Internal Server Error. \n Error occurred while getting the review list.",
response = ErrorResponse.class) response = ErrorResponse.class)
}) })
Response getAllReleaseReviews( Response getUserReviews(
@ApiParam( @ApiParam(
name="uuid", name="uuid",
value="uuid of the application release.", value="uuid of the application release.",
@ -140,105 +141,55 @@ public interface ReviewManagementAPI {
defaultValue = "20") defaultValue = "20")
@QueryParam("limit") int limit); @QueryParam("limit") int limit);
@GET @GET
@Path("/app/user/{uuid}") @Path("/app/{uuid}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "GET", httpMethod = "GET",
value = "get app reviews", value = "get app reviews",
notes = "Get all app reviews", notes = "Get all app reviews",
tags = "Store Management", tags = "Store Management",
extensions = { extensions = {
@Extension(properties = { @Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:review:view") @ExtensionProperty(name = SCOPE, value = "perm:app:review:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved app reviews.",
response = PaginationResult.class,
responseContainer = "PaginationResult"),
@ApiResponse(
code = 404,
message = "Not Found. \n Not found an application release associated with requested "
+ "UUID."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting the review list.",
response = ErrorResponse.class)
}) })
}
)
Response getUserReviews( @ApiResponses(
@ApiParam( value = {
name="uuid", @ApiResponse(
value="uuid of the application release.", code = 200,
required = true) message = "OK. \n Successfully retrieved app reviews.",
@PathParam("uuid") String uuid, response = PaginationResult.class,
@ApiParam( responseContainer = "PaginationResult"),
name="offset", @ApiResponse(
value="Starting review number.", code = 404,
defaultValue = "0") message = "Not Found. \n Not found an application release associated with requested "
@QueryParam("offSet") int offSet, + "UUID."),
@ApiParam( @ApiResponse(
name="limit", code = 500,
value = "Limit of paginated reviews", message = "Internal Server Error. \n Error occurred while getting the review list.",
defaultValue = "20") response = ErrorResponse.class)
@QueryParam("limit") int limit); })
@GET
@Path("/app/{uuid}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "get app reviews",
notes = "Get all app reviews",
tags = "Store Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:review:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved app reviews.",
response = PaginationResult.class,
responseContainer = "PaginationResult"),
@ApiResponse(
code = 404,
message = "Not Found. \n Not found an application release associated with requested "
+ "UUID."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting the review list.",
response = ErrorResponse.class)
})
Response getAllAppReviews( Response getAllAppReviews(
@ApiParam( @ApiParam(
name="uuid", name="uuid",
value="uuid of the application release.", value="uuid of the application release.",
required = true) required = true)
@PathParam("uuid") String uuid, @PathParam("uuid") String uuid,
@ApiParam( @ApiParam(
name="offset", name="offset",
value="Starting review number.", value="Starting review number.",
defaultValue = "0") defaultValue = "0")
@QueryParam("offSet") int offSet, @QueryParam("offSet") int offSet,
@ApiParam( @ApiParam(
name="limit", name="limit",
value = "Limit of paginated reviews", value = "Limit of paginated reviews",
defaultValue = "20") defaultValue = "20")
@QueryParam("limit") int limit); @QueryParam("limit") int limit);
@POST @POST
@Path("/{uuid}") @Path("/{uuid}")
@ -442,13 +393,13 @@ public interface ReviewManagementAPI {
@PathParam("reviewId") int reviewId); @PathParam("reviewId") int reviewId);
@GET @GET
@Path("/{uuid}/release-rating") @Path("/{uuid}/app-rating")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "GET", httpMethod = "GET",
value = "get ratings", value = "get app ratings",
notes = "Get all ratings", notes = "Get all app ratings",
tags = "Store Management", tags = "Store Management",
extensions = { extensions = {
@Extension(properties = { @Extension(properties = {
@ -466,7 +417,7 @@ public interface ReviewManagementAPI {
responseContainer = "List"), responseContainer = "List"),
@ApiResponse( @ApiResponse(
code = 404, code = 404,
message = "Not Found. \n No Application release found for application release UUID.", message = "Not Found. \n No Application found which has application release of UUID.",
response = ErrorResponse.class), response = ErrorResponse.class),
@ApiResponse( @ApiResponse(
code = 500, code = 500,
@ -474,52 +425,11 @@ public interface ReviewManagementAPI {
response = ErrorResponse.class) response = ErrorResponse.class)
}) })
Response getAppReleaseRating( Response getAppRating(
@ApiParam( @ApiParam(
name = "uuid", name = "uuid",
value = "uuid of the application release", value = "uuid of the application release",
required = true) required = true)
@PathParam("uuid") @PathParam("uuid")
String uuid); String uuid);
@GET
@Path("/{uuid}/app-rating")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "get app ratings",
notes = "Get all app ratings",
tags = "Store Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:app:review:view")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully retrieved ratings.",
response = List.class,
responseContainer = "List"),
@ApiResponse(
code = 404,
message = "Not Found. \n No Application found which has application release of UUID.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while getting ratings",
response = ErrorResponse.class)
})
Response getAppRating(
@ApiParam(
name = "uuid",
value = "uuid of the application release",
required = true)
@PathParam("uuid")
String uuid);
} }

@ -1,174 +0,0 @@
/* 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.store.api.services.admin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.application.mgt.common.ErrorResponse;
import org.wso2.carbon.device.application.mgt.common.response.Review;
import org.wso2.carbon.device.application.mgt.common.wrapper.ReviewWrapper;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* APIs to handle review management related tasks.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "Review Management Admin Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "ReviewManagementAdminService"),
@ExtensionProperty(name = "context", value = "/api/application-mgt/v1.0/admin/review"),
})
}
),
tags = {
@Tag(name = "review_management", description = "Review Management related Admin APIs")
}
)
@Scopes(
scopes = {
@Scope(
name = "Update a Review",
description = "Update a Review from the application store.",
key = "perm:admin:app:review:update",
permissions = {"/app-mgt/store/admin/review/update"}
)
}
)
@Path("/admin/reviews")
@Api(value = "Review Management Admin API")
@Produces(MediaType.APPLICATION_JSON)
public interface ReviewManagementAdminAPI {
String SCOPE = "scope";
@PUT
@Path("/{uuid}/{reviewId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "PUT",
value = "Edit a reviewTmp",
notes = "This will edit the reviewTmp",
tags = "Store Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:update")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully updated reviewTmp.",
response = Review.class),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while updating the new reviewTmp.",
response = ErrorResponse.class)
})
Response updateReview(
@ApiParam(
name = "reviewTmp",
value = "The reviewTmp that need to be updated.",
required = true)
@Valid ReviewWrapper updatingReview,
@ApiParam(
name = "uuid",
value = "uuid of the application release",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(
name = "reviewId",
value = "reviewTmp id of the updating reviewTmp.",
required = true)
@PathParam("reviewId") int reviewId);
@DELETE
@Path("/{uuid}/{reviewId}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "DELETE",
value = "Remove comment",
notes = "Remove comment",
tags = "Store Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:admin:app:review:update")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deleted the review"),
@ApiResponse(
code = 404,
message = "Not Found. \n No activity found with the given ID.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Error occurred while deleting the review.",
response = ErrorResponse.class)
})
Response deleteReview(
@ApiParam(
name = "uuid",
value = "UUID of the application release.",
required = true)
@PathParam("uuid") String uuid,
@ApiParam(name = "reviewId",
value = "Id of the review.",
required = true)
@PathParam("reviewId") int reviewId);
}

@ -53,33 +53,6 @@ public class ReviewManagementAPIImpl implements ReviewManagementAPI {
private static Log log = LogFactory.getLog(ReviewManagementAPIImpl.class); private static Log log = LogFactory.getLog(ReviewManagementAPIImpl.class);
@Override
@GET
@Path("/release/{uuid}")
public Response getAllReleaseReviews(
@PathParam("uuid") String uuid,
@DefaultValue("0") @QueryParam("offset") int offSet,
@DefaultValue("20") @QueryParam("limit") int limit) {
ReviewManager reviewManager = APIUtil.getReviewManager();
PaginationRequest request = new PaginationRequest(offSet, limit);
try {
PaginationResult paginationResult = reviewManager.getAllReleaseReviews(request, uuid);
return Response.status(Response.Status.OK).entity(paginationResult).build();
} catch (NotFoundException e) {
String msg = "Couldn't find an application release for UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (ReviewManagementException e) {
String msg = "Error occurred while retrieving reviews for application UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (ApplicationManagementException e) {
String msg = "Error occurred while retrieving application release details for application UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
@Override @Override
@GET @GET
@Path("/app/user/{uuid}") @Path("/app/user/{uuid}")
@ -281,27 +254,6 @@ public class ReviewManagementAPIImpl implements ReviewManagementAPI {
} }
} }
@Override
@GET
@Path("/{uuid}/release-rating")
public Response getAppReleaseRating(
@PathParam("uuid") String uuid) {
ReviewManager reviewManager = APIUtil.getReviewManager();
Rating rating;
try {
rating = reviewManager.getAppReleaseRating(uuid);
} catch (NotFoundException e) {
String msg = "Couldn't found an application release for UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
} catch (ReviewManagementException | ApplicationManagementException e) {
String msg = "Error occured while getting review data for application release UUID: " + uuid;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.OK).entity(rating).build();
}
@Override @Override
@GET @GET
@Path("/{uuid}/app-rating") @Path("/{uuid}/app-rating")

@ -26,7 +26,6 @@
<jaxrs:serviceBeans> <jaxrs:serviceBeans>
<ref bean="applicationMgtServiceBean"/> <ref bean="applicationMgtServiceBean"/>
<ref bean="reviewMgtServiceBean"/> <ref bean="reviewMgtServiceBean"/>
<ref bean="reviewMgtAdminServiceBean"/>
<ref bean="subscriptionMgtServiceBean"/> <ref bean="subscriptionMgtServiceBean"/>
<ref bean="swaggerResource"/> <ref bean="swaggerResource"/>
</jaxrs:serviceBeans> </jaxrs:serviceBeans>
@ -56,7 +55,6 @@
<bean id="applicationMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ApplicationManagementAPIImpl"/> <bean id="applicationMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ApplicationManagementAPIImpl"/>
<bean id="reviewMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ReviewManagementAPIImpl" /> <bean id="reviewMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.ReviewManagementAPIImpl" />
<bean id="reviewMgtAdminServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.admin.ReviewManagementAdminAPIImpl" />
<bean id="subscriptionMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.SubscriptionManagementAPIImpl"/> <bean id="subscriptionMgtServiceBean" class="org.wso2.carbon.device.application.mgt.store.api.services.impl.SubscriptionManagementAPIImpl"/>
<bean id="jsonProvider" class="org.wso2.carbon.device.application.mgt.addons.JSONMessageHandler"/> <bean id="jsonProvider" class="org.wso2.carbon.device.application.mgt.addons.JSONMessageHandler"/>
<bean id="multipartProvider" class="org.wso2.carbon.device.application.mgt.addons.MultipartCustomProvider"/> <bean id="multipartProvider" class="org.wso2.carbon.device.application.mgt.addons.MultipartCustomProvider"/>

@ -42,7 +42,6 @@
<module>org.wso2.carbon.device.application.mgt.store.api</module> <module>org.wso2.carbon.device.application.mgt.store.api</module>
<module>org.wso2.carbon.device.application.mgt.publisher.ui</module> <module>org.wso2.carbon.device.application.mgt.publisher.ui</module>
<module>org.wso2.carbon.device.application.mgt.store.ui</module> <module>org.wso2.carbon.device.application.mgt.store.ui</module>
<module>org.wso2.carbon.device.application.mgt.handler</module>
<module>org.wso2.carbon.device.application.mgt.api</module> <module>org.wso2.carbon.device.application.mgt.api</module>
</modules> </modules>

@ -151,5 +151,10 @@
<artifactId>org.wso2.carbon.device.application.mgt.common</artifactId> <artifactId>org.wso2.carbon.device.application.mgt.common</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -24,12 +24,17 @@ import com.google.gson.JsonParser;
import io.entgra.ui.request.interceptor.beans.AuthData; import io.entgra.ui.request.interceptor.beans.AuthData;
import io.entgra.ui.request.interceptor.util.HandlerConstants; import io.entgra.ui.request.interceptor.util.HandlerConstants;
import io.entgra.ui.request.interceptor.util.HandlerUtil; import io.entgra.ui.request.interceptor.util.HandlerUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
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.apache.http.HttpHeaders; import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpPut;
@ -38,6 +43,9 @@ import org.apache.http.cookie.SM;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.wso2.carbon.device.application.mgt.common.ProxyResponse; import org.wso2.carbon.device.application.mgt.common.ProxyResponse;
import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.MultipartConfig;
@ -48,8 +56,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.io.IOException; import java.io.IOException;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List;
import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute;
@MultipartConfig @MultipartConfig
@WebServlet( @WebServlet(
@ -61,38 +68,21 @@ import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute;
} }
) )
public class InvokerHandler extends HttpServlet { public class InvokerHandler extends HttpServlet {
private static final Log log = LogFactory.getLog(LoginHandler.class); private static final Log log = LogFactory.getLog(InvokerHandler.class);
private static final long serialVersionUID = -6508020875358160165L; private static final long serialVersionUID = -6508020875358160165L;
// private static final HeaderGroup nonForwardingHeaders = new HeaderGroup(); private AuthData authData;
private static AuthData authData; private String apiEndpoint;
private static String apiEndpoint; private String serverUrl;
private static String serverUrl; private String platform;
private static String platform;
// static {
// // Initializing hop-by-hop headers to omit them from forwarding to the backend
// String[] headers = {HttpHeaders.CONNECTION, HttpHeaders.TRANSFER_ENCODING, HttpHeaders.PROXY_AUTHENTICATE,
// HttpHeaders.PROXY_AUTHORIZATION, HttpHeaders.UPGRADE, HttpHeaders.TE, HttpHeaders.TRAILER,
// HandlerConstants.KEEP_ALIVE, HandlerConstants.PUBLIC};
// for (String header : headers) {
// nonForwardingHeaders.addHeader(new BasicHeader(header, null));
// }
// }
@Override @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) { protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
try { try {
if (validateRequest(req, resp)) { if (validateRequest(req, resp)) {
HttpPost postRequest = new HttpPost(generateBackendRequestURL(req)); HttpPost postRequest = new HttpPost(generateBackendRequestURL(req));
if (StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) || generateRequestEntity(req, postRequest);
StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) {
InputStreamEntity entity = new InputStreamEntity(req.getInputStream(),
Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH)));
postRequest.setEntity(entity);
}
copyRequestHeaders(req, postRequest);
postRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); postRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken());
ProxyResponse proxyResponse = execute(postRequest); ProxyResponse proxyResponse = HandlerUtil.execute(postRequest);
if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) {
proxyResponse = retryRequestWithRefreshedToken(req, resp, postRequest); proxyResponse = retryRequestWithRefreshedToken(req, resp, postRequest);
@ -107,6 +97,8 @@ public class InvokerHandler extends HttpServlet {
} }
HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse);
} }
} catch (FileUploadException e) {
log.error("Error occurred when processing Multipart POST request.", e);
} catch (IOException e) { } catch (IOException e) {
log.error("Error occurred when processing POST request.", e); log.error("Error occurred when processing POST request.", e);
} }
@ -117,9 +109,9 @@ public class InvokerHandler extends HttpServlet {
try { try {
if (validateRequest(req, resp)) { if (validateRequest(req, resp)) {
HttpGet getRequest = new HttpGet(generateBackendRequestURL(req)); HttpGet getRequest = new HttpGet(generateBackendRequestURL(req));
copyRequestHeaders(req, getRequest); copyRequestHeaders(req, getRequest, false);
getRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); getRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken());
ProxyResponse proxyResponse = execute(getRequest); ProxyResponse proxyResponse = HandlerUtil.execute(getRequest);
if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) {
proxyResponse = retryRequestWithRefreshedToken(req, resp, getRequest); proxyResponse = retryRequestWithRefreshedToken(req, resp, getRequest);
if (proxyResponse == null) { if (proxyResponse == null) {
@ -143,16 +135,9 @@ public class InvokerHandler extends HttpServlet {
try { try {
if (validateRequest(req, resp)) { if (validateRequest(req, resp)) {
HttpPut putRequest = new HttpPut(generateBackendRequestURL(req)); HttpPut putRequest = new HttpPut(generateBackendRequestURL(req));
if ((StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) && generateRequestEntity(req, putRequest);
Double.parseDouble(req.getHeader(HttpHeaders.CONTENT_LENGTH)) > 0) ||
StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) {
InputStreamEntity entity = new InputStreamEntity(req.getInputStream(),
Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH)));
putRequest.setEntity(entity);
}
copyRequestHeaders(req, putRequest);
putRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); putRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken());
ProxyResponse proxyResponse = execute(putRequest); ProxyResponse proxyResponse = HandlerUtil.execute(putRequest);
if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) {
proxyResponse = retryRequestWithRefreshedToken(req, resp, putRequest); proxyResponse = retryRequestWithRefreshedToken(req, resp, putRequest);
@ -167,6 +152,8 @@ public class InvokerHandler extends HttpServlet {
} }
HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse);
} }
} catch (FileUploadException e) {
log.error("Error occurred when processing Multipart PUT request.", e);
} catch (IOException e) { } catch (IOException e) {
log.error("Error occurred when processing PUT request.", e); log.error("Error occurred when processing PUT request.", e);
} }
@ -177,9 +164,9 @@ public class InvokerHandler extends HttpServlet {
try { try {
if (validateRequest(req, resp)) { if (validateRequest(req, resp)) {
HttpDelete deleteRequest = new HttpDelete(generateBackendRequestURL(req)); HttpDelete deleteRequest = new HttpDelete(generateBackendRequestURL(req));
copyRequestHeaders(req, deleteRequest); copyRequestHeaders(req, deleteRequest, false);
deleteRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); deleteRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken());
ProxyResponse proxyResponse = execute(deleteRequest); ProxyResponse proxyResponse = HandlerUtil.execute(deleteRequest);
if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) {
proxyResponse = retryRequestWithRefreshedToken(req, resp, deleteRequest); proxyResponse = retryRequestWithRefreshedToken(req, resp, deleteRequest);
if (proxyResponse == null) { if (proxyResponse == null) {
@ -198,6 +185,49 @@ public class InvokerHandler extends HttpServlet {
} }
} }
/**
* Generate te request entity for POST and PUT requests from the incoming request.
*
* @param req incoming {@link HttpServletRequest}.
* @param proxyRequest proxy request instance.
* @throws FileUploadException If unable to parse the incoming request for multipart content extraction.
* @throws IOException If error occurred while generating the request body.
*/
private void generateRequestEntity(HttpServletRequest req, HttpEntityEnclosingRequestBase proxyRequest)
throws FileUploadException, IOException {
if (ServletFileUpload.isMultipartContent(req)) {
ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> fileItemList = servletFileUpload.parseRequest(req);
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
for (FileItem item: fileItemList) {
if (!item.isFormField()) {
entityBuilder.addPart(item.getFieldName(), new InputStreamBody(item.getInputStream(),
ContentType.create(item.getContentType()), item.getName()));
} else {
entityBuilder.addTextBody(item.getFieldName(), item.getString(),
ContentType.create(item.getContentType()));
}
}
proxyRequest.setEntity(entityBuilder.build());
copyRequestHeaders(req, proxyRequest, false);
} else {
if (StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) ||
StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) {
InputStreamEntity entity = new InputStreamEntity(req.getInputStream(),
Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH)));
proxyRequest.setEntity(entity);
}
copyRequestHeaders(req, proxyRequest, true);
}
}
/**
* Generates the target URL for the proxy request.
*
* @param req incoming {@link HttpServletRequest}
* @return Target URL
*/
private String generateBackendRequestURL(HttpServletRequest req) { private String generateBackendRequestURL(HttpServletRequest req) {
StringBuilder urlBuilder = new StringBuilder(); StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(serverUrl).append(HandlerConstants.API_COMMON_CONTEXT).append(apiEndpoint); urlBuilder.append(serverUrl).append(HandlerConstants.API_COMMON_CONTEXT).append(apiEndpoint);
@ -207,12 +237,22 @@ public class InvokerHandler extends HttpServlet {
return urlBuilder.toString(); return urlBuilder.toString();
} }
private void copyRequestHeaders(HttpServletRequest req, HttpRequestBase httpRequest) { /**
* Copy incoming request headers to the proxy request.
*
* @param req incoming {@link HttpServletRequest}
* @param httpRequest proxy request instance.
* @param preserveContentType <code>true</code> if content type header needs to be preserved.
* This should be set to <code>false</code> when handling multipart requests as Http
* client will generate the Content-Type header automatically.
*/
private void copyRequestHeaders(HttpServletRequest req, HttpRequestBase httpRequest, boolean preserveContentType) {
Enumeration<String> headerNames = req.getHeaderNames(); Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) { while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement(); String headerName = headerNames.nextElement();
if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH) || if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH) ||
headerName.equalsIgnoreCase(SM.COOKIE)) { headerName.equalsIgnoreCase(SM.COOKIE) ||
(!preserveContentType && headerName.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE))) {
continue; continue;
} }
Enumeration<String> headerValues = req.getHeaders(headerName); Enumeration<String> headerValues = req.getHeaders(headerName);
@ -221,46 +261,46 @@ public class InvokerHandler extends HttpServlet {
} }
} }
} }
/*** /***
* Validates the incoming request.
* *
* @param req {@link HttpServletRequest} * @param req {@link HttpServletRequest}
* @param resp {@link HttpServletResponse} * @param resp {@link HttpServletResponse}
* @return If request is a valid one, returns TRUE, otherwise return FALSE * @return If request is a valid one, returns TRUE, otherwise return FALSE
* @throws IOException If and error occurs while witting error response to client side * @throws IOException If and error occurs while witting error response to client side
*/ */
private static boolean validateRequest(HttpServletRequest req, HttpServletResponse resp) private boolean validateRequest(HttpServletRequest req, HttpServletResponse resp)
throws IOException { throws IOException {
serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort(); serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
apiEndpoint = req.getPathInfo(); apiEndpoint = req.getPathInfo();
platform = req.getHeader(HandlerConstants.X_PLATFORM_HEADER);
HttpSession session = req.getSession(false); HttpSession session = req.getSession(false);
if (session == null) { if (session == null) {
log.error("Unauthorized, You are not logged in. Please log in to the portal"); log.error("Unauthorized, You are not logged in. Please log in to the portal");
ProxyResponse proxyResponse = new ProxyResponse(); handleError(req, resp, HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); return false;
proxyResponse.setExecutorResponse( }
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); if (StringUtils.isEmpty(platform)) {
log.error("\"X-Platform\" header is empty in the request. Header is required to obtain the auth data from" +
" session.");
handleError(req, resp, HttpStatus.SC_BAD_REQUEST);
return false; return false;
} }
authData = (AuthData) session.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY);
platform = (String) session.getAttribute(HandlerConstants.PLATFORM); authData = (AuthData) session.getAttribute(platform);
if (authData == null) { if (authData == null) {
log.error("Unauthorized, Access token not found in the current session"); log.error("Unauthorized, Access token not found in the current session");
ProxyResponse proxyResponse = new ProxyResponse(); handleError(req, resp, HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false; return false;
} }
if (apiEndpoint == null || req.getMethod() == null) { if (apiEndpoint == null || req.getMethod() == null) {
log.error("Bad Request, Either destination api-endpoint or method is empty"); log.error("Bad Request, Either destination api-endpoint or method is empty");
ProxyResponse proxyResponse = new ProxyResponse(); handleError(req, resp, HttpStatus.SC_BAD_REQUEST);
proxyResponse.setCode(HttpStatus.SC_BAD_REQUEST);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_BAD_REQUEST));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false; return false;
} }
return true; return true;
@ -275,11 +315,11 @@ public class InvokerHandler extends HttpServlet {
* @return {@link ProxyResponse} if successful and <code>null</code> if failed. * @return {@link ProxyResponse} if successful and <code>null</code> if failed.
* @throws IOException If an error occurs when try to retry the request. * @throws IOException If an error occurs when try to retry the request.
*/ */
private static ProxyResponse retryRequestWithRefreshedToken(HttpServletRequest req, HttpServletResponse resp, private ProxyResponse retryRequestWithRefreshedToken(HttpServletRequest req, HttpServletResponse resp,
HttpRequestBase httpRequest) throws IOException { HttpRequestBase httpRequest) throws IOException {
if (refreshToken(req, resp)) { if (refreshToken(req, resp)) {
httpRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); httpRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken());
ProxyResponse proxyResponse = execute(httpRequest); ProxyResponse proxyResponse = HandlerUtil.execute(httpRequest);
if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while invoking the API after refreshing the token."); log.error("Error occurred while invoking the API after refreshing the token.");
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
@ -297,7 +337,7 @@ public class InvokerHandler extends HttpServlet {
* @return If successfully renew tokens, returns TRUE otherwise return FALSE * @return If successfully renew tokens, returns TRUE otherwise return FALSE
* @throws IOException If an error occurs while witting error response to client side or invoke token renewal API * @throws IOException If an error occurs while witting error response to client side or invoke token renewal API
*/ */
private static boolean refreshToken(HttpServletRequest req, HttpServletResponse resp) private boolean refreshToken(HttpServletRequest req, HttpServletResponse resp)
throws IOException { throws IOException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("refreshing the token"); log.debug("refreshing the token");
@ -307,11 +347,7 @@ public class InvokerHandler extends HttpServlet {
HttpSession session = req.getSession(false); HttpSession session = req.getSession(false);
if (session == null) { if (session == null) {
log.error("Couldn't find a session, hence it is required to login and proceed."); log.error("Couldn't find a session, hence it is required to login and proceed.");
ProxyResponse proxyResponse = new ProxyResponse(); handleError(req, resp, HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED);
proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false; return false;
} }
@ -325,7 +361,7 @@ public class InvokerHandler extends HttpServlet {
encodedClientApp); encodedClientApp);
tokenEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString()); tokenEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString());
ProxyResponse tokenResultResponse = execute(tokenEndpoint); ProxyResponse tokenResultResponse = HandlerUtil.execute(tokenEndpoint);
if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
log.error("Error occurred while refreshing access token."); log.error("Error occurred while refreshing access token.");
HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse); HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse);
@ -352,11 +388,24 @@ public class InvokerHandler extends HttpServlet {
} }
log.error("Error Occurred in token renewal process."); log.error("Error Occurred in token renewal process.");
handleError(req, resp, HttpStatus.SC_INTERNAL_SERVER_ERROR);
return false;
}
/**
* Handle error requests
*
* @param req {@link HttpServletRequest}
* @param resp {@link HttpServletResponse}
* @param errorCode HTTP error status code
* @throws IOException If error occurred when trying to send the error response.
*/
private void handleError(HttpServletRequest req, HttpServletResponse resp, int errorCode)
throws IOException {
ProxyResponse proxyResponse = new ProxyResponse(); ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); proxyResponse.setCode(errorCode);
proxyResponse.setExecutorResponse( proxyResponse.setExecutorResponse(
HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_INTERNAL_SERVER_ERROR)); HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(errorCode));
HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
return false;
} }
} }

@ -50,8 +50,6 @@ import javax.servlet.http.HttpSession;
import java.io.IOException; import java.io.IOException;
import java.util.Base64; import java.util.Base64;
import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute;
@MultipartConfig @MultipartConfig
@WebServlet("/login") @WebServlet("/login")
public class LoginHandler extends HttpServlet { public class LoginHandler extends HttpServlet {
@ -78,12 +76,12 @@ public class LoginHandler extends HttpServlet {
httpSession.invalidate(); httpSession.invalidate();
} }
httpSession = req.getSession(true); httpSession = req.getSession(true);
//setting session to expiry in 5 mins //setting session to expiry in 5 minutes
httpSession.setMaxInactiveInterval(Math.toIntExact(HandlerConstants.TIMEOUT)); httpSession.setMaxInactiveInterval(Math.toIntExact(HandlerConstants.TIMEOUT));
HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl); HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl);
JsonParser jsonParser = new JsonParser(); JsonParser jsonParser = new JsonParser();
ProxyResponse uiConfigResponse = execute(uiConfigEndpoint); ProxyResponse uiConfigResponse = HandlerUtil.execute(uiConfigEndpoint);
String executorResponse = uiConfigResponse.getExecutorResponse(); String executorResponse = uiConfigResponse.getExecutorResponse();
if (!StringUtils.isEmpty(executorResponse) && executorResponse if (!StringUtils.isEmpty(executorResponse) && executorResponse
.contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { .contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
@ -126,26 +124,25 @@ public class LoginHandler extends HttpServlet {
apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
apiRegEndpoint.setEntity(constructAppRegPayload(tags)); apiRegEndpoint.setEntity(constructAppRegPayload(tags));
ProxyResponse clientAppResponse = execute(apiRegEndpoint); ProxyResponse clientAppResponse = HandlerUtil.execute(apiRegEndpoint);
String clientAppResult = clientAppResponse.getData(); String clientAppResult = clientAppResponse.getData();
if (!StringUtils.isEmpty(clientAppResult) && getTokenAndPersistInSession(req, resp, if (!StringUtils.isEmpty(clientAppResult) && getTokenAndPersistInSession(req, resp,
clientAppResponse.getData(), scopes)) { clientAppResponse.getData(), scopes)) {
ProxyResponse proxyResponse = new ProxyResponse(); ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_OK); proxyResponse.setCode(HttpStatus.SC_OK);
proxyResponse.setUrl(serverUrl + "/" + platform + uiConfigJsonObject.get(HandlerConstants.LOGIN_RESPONSE_KEY) proxyResponse.setUrl(serverUrl + "/" + platform);
.getAsJsonObject().get("successCallback").getAsString());
HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse);
return; return;
} }
HandlerUtil.handleError(req, resp, serverUrl, platform, null); HandlerUtil.handleError(req, resp, serverUrl, platform, null);
} }
} catch (IOException e) { } catch (IOException e) {
log.error("Error occured while sending the response into the socket. ", e); log.error("Error occurred while sending the response into the socket. ", e);
} catch (JsonSyntaxException e) { } catch (JsonSyntaxException e) {
log.error("Error occured while parsing the response. ", e); log.error("Error occurred while parsing the response. ", e);
} catch (LoginException e) { } catch (LoginException e) {
log.error("Error occured while getting token data. ", e); log.error("Error occurred while getting token data. ", e);
} }
} }
@ -196,14 +193,14 @@ public class LoginHandler extends HttpServlet {
authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString());
authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString());
authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString());
session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData); session.setAttribute(platform, authData);
return true; return true;
} }
} }
return false; return false;
} catch (IOException e) { } catch (IOException e) {
throw new LoginException("Error occured while sending the response into the socket", e); throw new LoginException("Error occurred while sending the response into the socket", e);
} }
} }
@ -216,8 +213,8 @@ public class LoginHandler extends HttpServlet {
if (scopes != null && scopes.size() > 0) { if (scopes != null && scopes.size() > 0) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (JsonElement scope : scopes) { for (JsonElement scope : scopes) {
String tmpscope = scope.getAsString() + " "; String tmpScope = scope.getAsString() + " ";
builder.append(tmpscope); builder.append(tmpScope);
} }
return builder.toString(); return builder.toString();
} else { } else {
@ -248,7 +245,7 @@ public class LoginHandler extends HttpServlet {
" Invalid login request. Username or Password is not received for login request."); " Invalid login request. Username or Password is not received for login request.");
} }
} catch (IOException e) { } catch (IOException e) {
throw new LoginException("Error Occured while redirecting to default error page.", e); throw new LoginException("Error occurred while redirecting to default error page.", e);
} }
} }
@ -271,13 +268,13 @@ public class LoginHandler extends HttpServlet {
* @param encodedClientApp - Base64 encoded clientId:clientSecret. * @param encodedClientApp - Base64 encoded clientId:clientSecret.
* @param scopes - Scopes which are retrieved by reading application-mgt configuration * @param scopes - Scopes which are retrieved by reading application-mgt configuration
* @return Invoke token endpoint and return the response as string. * @return Invoke token endpoint and return the response as string.
* @throws IOException IO exception throws if an error occured when invoking token endpoint * @throws IOException IO exception throws if an error occurred when invoking token endpoint
*/ */
private ProxyResponse getTokenResult(String encodedClientApp, JsonArray scopes) throws IOException { private ProxyResponse getTokenResult(String encodedClientApp, JsonArray scopes) throws IOException {
HttpPost tokenEndpoint = new HttpPost(serverUrl + HandlerConstants.TOKEN_ENDPOINT); HttpPost tokenEndpoint = new HttpPost(serverUrl + HandlerConstants.TOKEN_ENDPOINT);
tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp); tokenEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + encodedClientApp);
tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString()); tokenEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString());
String scopeString = getScopeString(scopes); String scopeString = getScopeString(scopes);
if (scopeString != null) { if (scopeString != null) {
@ -290,6 +287,6 @@ public class LoginHandler extends HttpServlet {
"grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString, "grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString,
ContentType.APPLICATION_FORM_URLENCODED); ContentType.APPLICATION_FORM_URLENCODED);
tokenEndpoint.setEntity(tokenEPPayload); tokenEndpoint.setEntity(tokenEPPayload);
return execute(tokenEndpoint); return HandlerUtil.execute(tokenEndpoint);
} }
} }

@ -23,8 +23,6 @@ public class HandlerConstants {
public static final String APP_REG_ENDPOINT = "/api-application-registration/register"; public static final String APP_REG_ENDPOINT = "/api-application-registration/register";
public static final String UI_CONFIG_ENDPOINT = "/api/application-mgt/v1.0/config/ui-config"; public static final String UI_CONFIG_ENDPOINT = "/api/application-mgt/v1.0/config/ui-config";
public static final String TOKEN_ENDPOINT = "/oauth2/token"; public static final String TOKEN_ENDPOINT = "/oauth2/token";
public static final String PUBLIC = "Public";
public static final String KEEP_ALIVE = "Keep-Alive";
public static final String BASIC = "Basic "; public static final String BASIC = "Basic ";
public static final String BEARER = "Bearer "; public static final String BEARER = "Bearer ";
public static final String COLON = ":"; public static final String COLON = ":";
@ -33,14 +31,14 @@ public class HandlerConstants {
public static final String SESSION_AUTH_DATA_KEY = "application-mgt"; public static final String SESSION_AUTH_DATA_KEY = "application-mgt";
public static final String UI_CONFIG_KEY = "ui-config"; public static final String UI_CONFIG_KEY = "ui-config";
public static final String PLATFORM = "platform"; public static final String PLATFORM = "platform";
public static final String SERVER_HOST = "server-host";
public static final String DEFAULT_ERROR_CALLBACK = "/pages/error/default"; public static final String DEFAULT_ERROR_CALLBACK = "/pages/error/default";
public static final String LOGIN_RESPONSE_KEY = "loginResponse"; public static final String ERROR_CALLBACK_KEY = "errorCallback";
public static final String FAILURE_CALLBACK_KEY = "failureCallback";
public static final String API_COMMON_CONTEXT = "/api"; public static final String API_COMMON_CONTEXT = "/api";
public static final String EXECUTOR_EXCEPTION_PREFIX = "ExecutorException-"; public static final String EXECUTOR_EXCEPTION_PREFIX = "ExecutorException-";
public static final String TOKEN_IS_EXPIRED = "ACCESS_TOKEN_IS_EXPIRED"; public static final String TOKEN_IS_EXPIRED = "ACCESS_TOKEN_IS_EXPIRED";
public static final String X_PLATFORM_HEADER = "X-Platform";
public static final int INTERNAL_ERROR_CODE = 500; public static final int INTERNAL_ERROR_CODE = 500;
public static final long TIMEOUT = 1200; public static final long TIMEOUT = 1200;
} }

@ -20,12 +20,15 @@ package io.entgra.ui.request.interceptor.util;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
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.apache.http.Consts;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.json.JSONException; import org.json.JSONException;
@ -79,7 +82,7 @@ public class HandlerUtil {
if (jsonString.contains("Access token expired") || jsonString if (jsonString.contains("Access token expired") || jsonString
.contains("Invalid input. Access token validation failed")) { .contains("Invalid input. Access token validation failed")) {
proxyResponse.setCode(statusCode); proxyResponse.setCode(statusCode);
proxyResponse.setExecutorResponse("ACCESS_TOKEN_IS_EXPIRED"); proxyResponse.setExecutorResponse(HandlerConstants.TOKEN_IS_EXPIRED);
return proxyResponse; return proxyResponse;
} else { } else {
proxyResponse.setCode(statusCode); proxyResponse.setCode(statusCode);
@ -161,16 +164,15 @@ public class HandlerUtil {
} }
resp.setStatus(proxyResponse.getCode()); resp.setStatus(proxyResponse.getCode());
resp.setContentType("application/json"); resp.setContentType(ContentType.APPLICATION_JSON.getMimeType());
resp.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding(Consts.UTF_8.name());
if (httpSession != null) { if (httpSession != null) {
JsonObject uiConfig = (JsonObject) httpSession.getAttribute(HandlerConstants.UI_CONFIG_KEY); JsonObject uiConfig = (JsonObject) httpSession.getAttribute(HandlerConstants.UI_CONFIG_KEY);
if (uiConfig == null){ if (uiConfig == null){
proxyResponse.setUrl(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK); proxyResponse.setUrl(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK);
} else{ } else{
proxyResponse.setUrl(serverUrl + uiConfig.get(HandlerConstants.LOGIN_RESPONSE_KEY).getAsJsonObject() proxyResponse.setUrl(serverUrl + uiConfig.get(HandlerConstants.ERROR_CALLBACK_KEY).getAsJsonObject()
.get(HandlerConstants.FAILURE_CALLBACK_KEY).getAsJsonObject()
.get(proxyResponse.getExecutorResponse().split(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)[1]) .get(proxyResponse.getExecutorResponse().split(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)[1])
.getAsString()); .getAsString());
} }
@ -192,13 +194,13 @@ public class HandlerUtil {
public static void handleSuccess(HttpServletRequest req, HttpServletResponse resp, String serverUrl, public static void handleSuccess(HttpServletRequest req, HttpServletResponse resp, String serverUrl,
String platform, ProxyResponse proxyResponse) throws IOException { String platform, ProxyResponse proxyResponse) throws IOException {
if (proxyResponse == null){ if (proxyResponse == null){
handleError(req,resp,serverUrl,platform,proxyResponse); handleError(req, resp, serverUrl, platform, null);
return; return;
} }
resp.setStatus(proxyResponse.getCode()); resp.setStatus(proxyResponse.getCode());
resp.setContentType("application/json"); resp.setContentType(ContentType.APPLICATION_JSON.getMimeType());
resp.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding(Consts.UTF_8.name());
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
String redirectUrl = proxyResponse.getUrl(); String redirectUrl = proxyResponse.getUrl();

@ -135,7 +135,6 @@
<UIConfigs> <UIConfigs>
<EnableOAuth>true</EnableOAuth> <EnableOAuth>true</EnableOAuth>
<EnableSSO>false</EnableSSO> <EnableSSO>false</EnableSSO>
<EnableSSO>false</EnableSSO>
<AppRegistration> <AppRegistration>
<Tags> <Tags>
<Tag>application_management</Tag> <Tag>application_management</Tag>
@ -154,28 +153,26 @@
<Scope>perm:app:subscription:install</Scope> <Scope>perm:app:subscription:install</Scope>
<Scope>perm:app:subscription:uninstall</Scope> <Scope>perm:app:subscription:uninstall</Scope>
<Scope>perm:admin:app:review:update</Scope> <Scope>perm:admin:app:review:update</Scope>
<Scope>perm:admin:app:review:view</Scope>
<Scope>perm:admin:app:publisher:update</Scope> <Scope>perm:admin:app:publisher:update</Scope>
</Scopes> </Scopes>
<SSOConfiguration> <SSOConfiguration>
<Issuer>app-mgt</Issuer> <Issuer>app-mgt</Issuer>
</SSOConfiguration> </SSOConfiguration>
<LoginResponse> <ErrorCallback>
<SuccessCallback>/apps</SuccessCallback> <BadRequest>/pages/error/client-errors/400</BadRequest>
<FailureCallback> <Unauthorized>/pages/error/client-errors/401</Unauthorized>
<BadRequest>/pages/error/client-errors/400</BadRequest> <Forbidden>/pages/error/client-errors/403</Forbidden>
<Unauthorized>/pages/error/client-errors/401</Unauthorized> <NotFound>/pages/error/client-errors/404</NotFound>
<Forbidden>/pages/error/client-errors/403</Forbidden> <MethodNotAllowed>/pages/error/client-errors/405</MethodNotAllowed>
<NotFound>/pages/error/client-errors/404</NotFound> <NotAcceptable>/pages/error/client-errors/406</NotAcceptable>
<MethodNotAllowed>/pages/error/client-errors/405</MethodNotAllowed> <UnsupportedMediaType>/pages/error/client-errors/415</UnsupportedMediaType>
<NotAcceptable>/pages/error/client-errors/406</NotAcceptable> <InternalServerError>/pages/error/server-errors/500</InternalServerError>
<UnsupportedMediaType>/pages/error/client-errors/415</UnsupportedMediaType> <DefaultPage>/pages/error/default</DefaultPage>
<InternalServerError>/pages/error/server-errors/500</InternalServerError> </ErrorCallback>
<DefaultPage>/pages/error/default</DefaultPage>
</FailureCallback>
</LoginResponse>
</UIConfigs> </UIConfigs>
<ArtifactDownloadEndpoint>https://localhost:9443/api/application-mgt/v1.0/artifact</ArtifactDownloadEndpoint> <ArtifactDownloadEndpoint>/api/application-mgt/v1.0/artifact</ArtifactDownloadEndpoint>
<AppCategories> <AppCategories>
<Category>EMM</Category> <Category>EMM</Category>
<Category>IoT</Category> <Category>IoT</Category>

@ -1310,6 +1310,11 @@
<artifactId>httpcore</artifactId> <artifactId>httpcore</artifactId>
<version>${apache.http.core.version}</version> <version>${apache.http.core.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${apache.http.mime.version}</version>
</dependency>
<dependency> <dependency>
<groupId>commons-lang.wso2</groupId> <groupId>commons-lang.wso2</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
@ -2137,6 +2142,7 @@
<apache.http.client.version>4.5.6</apache.http.client.version> <apache.http.client.version>4.5.6</apache.http.client.version>
<!-- apache http components core --> <!-- apache http components core -->
<apache.http.core.version>4.4.10</apache.http.core.version> <apache.http.core.version>4.4.10</apache.http.core.version>
<apache.http.mime.version>4.5.8</apache.http.mime.version>
<jersey.version>1.9</jersey.version> <jersey.version>1.9</jersey.version>
<!-- Neethi version--> <!-- Neethi version-->

Loading…
Cancel
Save