From 65f5efb638aacf23c0c4ca5f7fe0e015c9cd8c8f Mon Sep 17 00:00:00 2001 From: Muhammad Rashad Date: Mon, 14 Mar 2022 06:09:01 +0000 Subject: [PATCH] Add APIs to get favourite apps --- .../entgra/application/mgt/common/Filter.java | 13 ++ .../mgt/common/dto/ApplicationDTO.java | 12 ++ .../mgt/common/response/Application.java | 12 ++ .../common/services/ApplicationManager.java | 23 ++++ .../mgt/core/dao/ApplicationDAO.java | 27 ++++ .../GenericApplicationDAOImpl.java | 114 ++++++++++++++-- .../application/OracleApplicationDAOImpl.java | 12 +- .../SQLServerApplicationDAOImpl.java | 8 +- .../mgt/core/impl/ApplicationManagerImpl.java | 119 +++++++++++++++++ .../application/mgt/core/util/APIUtil.java | 1 + .../services/ApplicationManagementAPI.java | 123 ++++++++++++++++++ .../impl/ApplicationManagementAPIImpl.java | 91 +++++++++++-- .../src/main/resources/conf/mdm-ui-config.xml | 1 + 13 files changed, 533 insertions(+), 23 deletions(-) diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Filter.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Filter.java index 6ce0f2b2d3..16858d7f90 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Filter.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Filter.java @@ -108,6 +108,11 @@ public class Filter { */ private String appReleaseState; + /** + * Username of whose favourite apps to be retrieved + */ + private String favouredBy; + public int getLimit() { return limit; } @@ -195,4 +200,12 @@ public class Filter { public String getAppReleaseType() { return appReleaseType; } public void setAppReleaseType(String appReleaseType) { this.appReleaseType = appReleaseType; } + + public String getFavouredBy() { + return favouredBy; + } + + public void setFavouredBy(String favouredBy) { + this.favouredBy = favouredBy; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/ApplicationDTO.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/ApplicationDTO.java index 48bd1c6822..2877c02f94 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/ApplicationDTO.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/ApplicationDTO.java @@ -96,6 +96,10 @@ public class ApplicationDTO { value = "package name of the application") private String packageName; + @ApiModelProperty(name = "isFavourite", + value = "if the app is favoured by the user") + private boolean isFavourite; + public String getPackageName() { return packageName; } @@ -189,4 +193,12 @@ public class ApplicationDTO { public double getAppRating() { return appRating; } public void setAppRating(double appRating) { this.appRating = appRating; } + + public boolean isFavourite() { + return isFavourite; + } + + public void setFavourite(boolean favourite) { + isFavourite = favourite; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/response/Application.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/response/Application.java index fc5251d3a8..0d11e7bfaa 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/response/Application.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/response/Application.java @@ -103,6 +103,10 @@ public class Application { value = "package name of the application") private String packageName; + @ApiModelProperty(name = "isFavourite", + value = "if the app is favoured by the user") + private boolean isFavourite; + public String getPackageName() { return packageName; } @@ -181,4 +185,12 @@ public class Application { public String getInstallerName() { return installerName; } public void setInstallerName(String installerName) { this.installerName = installerName; } + + public boolean isFavourite() { + return isFavourite; + } + + public void setFavourite(boolean favourite) { + isFavourite = favourite; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java index 018f9af7d9..46076344be 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java @@ -61,6 +61,27 @@ public interface ApplicationManager { Application createWebClip(WebAppWrapper webAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) throws ApplicationManagementException; + /** + * Add an application to favourites + * @param appId id of the application + * @throws ApplicationManagementException Catch all other throwing exceptions and throw {@link ApplicationManagementException} + */ + void addAppToFavourites(int appId) throws ApplicationManagementException; + + /** + * Remove an application from favourites + * @param appId id of the application + * @throws ApplicationManagementException Catch all other throwing exceptions and throw {@link ApplicationManagementException} + */ + void removeAppFromFavourites(int appId) throws ApplicationManagementException; + + /** + * Check if an application is a favourite app + * @param appId id of the application + * @throws ApplicationManagementException Catch all other throwing exceptions and throw {@link ApplicationManagementException} + */ + boolean isFavouriteApp(int appId) throws ApplicationManagementException; + Application createPublicApp(PublicAppWrapper publicAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) throws ApplicationManagementException; @@ -113,6 +134,8 @@ public interface ApplicationManager { */ void deleteApplicationRelease(String releaseUuid) throws ApplicationManagementException; + ApplicationList getFavouriteApplications(Filter filter) throws ApplicationManagementException; + /** * To get the applications based on the search filter. * diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/ApplicationDAO.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/ApplicationDAO.java index 6ffa843e5a..c64eba8814 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/ApplicationDAO.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/ApplicationDAO.java @@ -39,6 +39,33 @@ public interface ApplicationDAO { */ int createApplication(ApplicationDTO applicationDTO, int tenantId) throws ApplicationManagementDAOException; + /** + * Use to add an application to favourites for given appId, username and tenantId + * + * @param appId id of the application + * @param userName currently logged-in user + * @throws ApplicationManagementDAOException if error occurred wile executing query to insert data into database. + */ + void addAppToFavourite(int appId, String userName, int tenantId) throws ApplicationManagementDAOException; + + /** + * Use to remove an application from favourites for given appId, username and tenantId + * + * @param appId id of the application + * @param userName currently logged-in username + * @throws ApplicationManagementDAOException if error occurred wile executing query to delete data from database. + */ + void removeAppFromFavourite(int appId, String userName, int tenantId) throws ApplicationManagementDAOException; + + /** + * Use to check if an app is favourite for given username and tenantId + * @param appId id of the application + * @param userName currently logged-in username + * @return If application is favourite + * @throws ApplicationManagementDAOException if error occurred wile executing query to check if application is a favourite + */ + boolean isFavouriteApp(int appId, String userName, int tenantId) throws ApplicationManagementDAOException; + /** * To add tags for a particular application. * diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java index 9fa9743590..431369d449 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java @@ -24,7 +24,6 @@ import io.entgra.application.mgt.common.AppLifecycleState; import io.entgra.application.mgt.common.dto.ApplicationDTO; import io.entgra.application.mgt.common.dto.CategoryDTO; import io.entgra.application.mgt.common.Filter; -import io.entgra.application.mgt.common.dto.ReviewDTO; import io.entgra.application.mgt.common.dto.TagDTO; import io.entgra.application.mgt.common.exception.DBConnectionException; import io.entgra.application.mgt.core.dao.ApplicationDAO; @@ -136,10 +135,14 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT, " + "NEW_AP_APP_LIFECYCLE_STATE.UPDATED_AT AS LATEST_UPDATE " - + "FROM AP_APP " - + "INNER JOIN AP_APP_RELEASE ON " - + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " - + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP "; + + "FROM AP_APP "; + if (StringUtils.isNotEmpty(filter.getFavouredBy())) { + sql += "INNER JOIN AP_APP_FAVOURITES ON " + + "AP_APP.ID = AP_APP_FAVOURITES.AP_APP_ID "; + } + sql += "INNER JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP "; if (StringUtils.isNotEmpty(filter.getVersion()) || StringUtils.isNotEmpty(filter.getAppReleaseState()) || StringUtils.isNotEmpty(filter.getAppReleaseType())) { sql += "INNER JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; @@ -190,8 +193,11 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic + "FROM AP_APP_LIFECYCLE_STATE " + "GROUP BY AP_APP_LIFECYCLE_STATE.AP_APP_RELEASE_ID)) AS NEW_AP_APP_LIFECYCLE_STATE " + "ON AP_APP_RELEASE.ID = NEW_AP_APP_LIFECYCLE_STATE.AP_APP_RELEASE_ID " - + "WHERE AP_APP.TENANT_ID = ? " - + "ORDER BY AP_APP.ID, LATEST_UPDATE DESC"; + + "WHERE AP_APP.TENANT_ID = ? "; + if (StringUtils.isNotEmpty(filter.getFavouredBy())) { + sql += "AND AP_APP_FAVOURITES.USER_NAME = ? "; + } + sql += "ORDER BY AP_APP.ID, LATEST_UPDATE DESC"; try { Connection conn = this.getDBConnection(); @@ -230,7 +236,10 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic stmt.setInt(paramIndex++, filter.getLimit()); stmt.setInt(paramIndex++, filter.getOffset()); } - stmt.setInt(paramIndex, tenantId); + stmt.setInt(paramIndex++, tenantId); + if (StringUtils.isNotEmpty(filter.getFavouredBy())) { + stmt.setString(paramIndex, filter.getFavouredBy()); + } try (ResultSet rs = stmt.executeQuery()) { return DAOUtil.loadApplications(rs); } @@ -732,6 +741,95 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic } } + @Override + public void addAppToFavourite(int appId, String userName, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to add app with the id " + appId + " favourites"); + } + String sql = "INSERT INTO AP_APP_FAVOURITES " + + "(AP_APP_ID, USER_NAME, " + + " TENANT_ID) " + + "VALUES (?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, appId); + stmt.setString(2, userName); + stmt.setInt(3, tenantId); + stmt.addBatch(); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection when adding app to favourites"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while adding app with the id " + appId + " to favourites. Executed Query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void removeAppFromFavourite(int appId, String userName, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to add app with the id " + appId + " favourites"); + } + String sql = "DELETE FROM AP_APP_FAVOURITES " + + "WHERE AP_APP_ID = ? " + + "AND USER_NAME = ? " + + "AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, appId); + stmt.setString(2, userName); + stmt.setInt(3, tenantId); + stmt.addBatch(); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection when removing app from favourites"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "SQL Error occurred while removing app with the id " + appId + " from favourites. Executed Query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isFavouriteApp(int appId, String userName, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP_ID " + + "FROM AP_APP_FAVOURITES " + + "WHERE " + + "AP_APP_ID = ? AND " + + "USER_NAME = ? AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, appId); + stmt.setString(2, userName); + stmt.setInt(3, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check whether the application with the id " + + appId + " is a favourite app"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while obtaining the DB connection to check whether the application with the id " + + appId + " is a favourite app. executed query " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + @Override public void addTags(List tags, int tenantId) throws ApplicationManagementDAOException { if (log.isDebugEnabled()) { diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java index 60e49f2a27..da3d5e8aae 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java @@ -82,10 +82,14 @@ public class OracleApplicationDAOImpl extends GenericApplicationDAOImpl { + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT, " + "NEW_AP_APP_LIFECYCLE_STATE.UPDATED_AT AS LATEST_UPDATE " - + "FROM AP_APP " - + "INNER JOIN AP_APP_RELEASE ON " - + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " - + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP ORDER BY ID "; + + "FROM AP_APP "; + if (StringUtils.isNotEmpty(filter.getFavouredBy())) { + sql += "INNER JOIN AP_APP_FAVOURITES ON " + + "AP_APP.ID = AP_APP_FAVOURITES.AP_APP_ID "; + } + sql += "INNER JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP ORDER BY ID "; if (StringUtils.isNotEmpty(filter.getVersion()) || StringUtils.isNotEmpty(filter.getAppReleaseState()) || StringUtils.isNotEmpty(filter.getAppReleaseType())) { sql += "INNER JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java index 7420b9a057..1319c458e4 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java @@ -81,8 +81,12 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl { + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT, " + "NEW_AP_APP_LIFECYCLE_STATE.UPDATED_AT AS LATEST_UPDATE " - + "FROM AP_APP " - + "INNER JOIN AP_APP_RELEASE ON " + + "FROM AP_APP "; + if (StringUtils.isNotEmpty(filter.getFavouredBy())) { + sql += "INNER JOIN AP_APP_FAVOURITES ON " + + "AP_APP.ID = AP_APP_FAVOURITES.AP_APP_ID "; + } + sql += "INNER JOIN AP_APP_RELEASE ON " + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP "; if (StringUtils.isNotEmpty(filter.getVersion()) || StringUtils.isNotEmpty(filter.getAppReleaseState()) diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java index 599576f7b3..93f268cd73 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java @@ -178,6 +178,116 @@ ApplicationManagerImpl implements ApplicationManager { return addAppDataIntoDB(applicationDTO, tenantId, isPublished); } + @Override + public void addAppToFavourites(int appId) throws ApplicationManagementException { + validateAddAppToFavouritesRequest(appId); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + try { + ConnectionManagerUtil.beginDBTransaction(); + applicationDAO.addAppToFavourite(appId, userName, tenantId); + ConnectionManagerUtil.commitDBTransaction(); + } catch (TransactionManagementException e) { + String msg = "Error occurred while staring transaction to add applicationId: " + + appId + " to favourites"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while adding application id " + appId + " to favourites "; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while adding application with the id: " + appId + " to favourites "; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public void removeAppFromFavourites(int appId) throws ApplicationManagementException { + validateRemoveAppFromFavouritesRequest(appId); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + try { + ConnectionManagerUtil.beginDBTransaction(); + applicationDAO.removeAppFromFavourite(appId, userName, tenantId); + ConnectionManagerUtil.commitDBTransaction(); + } catch (TransactionManagementException e) { + String msg = "Error occurred while staring transaction to remove applicationId: " + + appId + " from favourites"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (DBConnectionException e) { + String msg = "Error occurred while removing application id " + appId + " from favourites "; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while removing application with the id: " + appId + " from favourites "; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public boolean isFavouriteApp(int appId) throws ApplicationManagementException{ + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + try { + ConnectionManagerUtil.openDBConnection(); + return applicationDAO.isFavouriteApp(appId, userName, tenantId); + } catch (DBConnectionException e) { + String msg = "Error occurred while getting DB connection to check is app with the id " + appId + + " is a favourite app"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while checking app with the id " + appId + " is a favourite app."; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + + } + + /** + * Use to check if the requested application id is valid before removing from favourites + * + * @param appId ID of the application + * @throws ApplicationManagementException if ID is not valid or errors while validating + */ + private void validateRemoveAppFromFavouritesRequest(int appId) throws ApplicationManagementException { + if (!isFavouriteApp(appId)) { + String msg = "Provided appId " + appId + " is not a favourite app in order remove from favourites"; + throw new BadRequestException(msg); + } + } + + /** + * Use to check if the requested application id is valid before adding to favourites + * + * @param appId ID of the application + * @throws ApplicationManagementException if ID is not valid or errors while validating + */ + private void validateAddAppToFavouritesRequest(int appId) throws ApplicationManagementException { + try { + getApplication(appId); + } catch (NotFoundException e) { + String msg = " No application exists for the provided appId " + appId; + throw new BadRequestException(msg); + } + if (isFavouriteApp(appId)) { + String msg = "Provided appId " + appId + " is already a favourite app"; + throw new BadRequestException(msg); + } + } + @Override public Application createPublicApp(PublicAppWrapper publicAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) throws ApplicationManagementException { @@ -608,9 +718,17 @@ ApplicationManagerImpl implements ApplicationManager { return applicationReleaseDTO; } + @Override + public ApplicationList getFavouriteApplications(Filter filter) throws ApplicationManagementException { + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + filter.setFavouredBy(userName); + return getApplications(filter); + } + @Override public ApplicationList getApplications(Filter filter) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); ApplicationList applicationList = new ApplicationList(); List applications = new ArrayList<>(); DeviceType deviceType; @@ -636,6 +754,7 @@ ApplicationManagerImpl implements ApplicationManager { .setUnrestrictedRoles(visibilityDAO.getUnrestrictedRoles(applicationDTO.getId(), tenantId)); applicationDTO.setAppCategories(applicationDAO.getAppCategories(applicationDTO.getId(), tenantId)); applicationDTO.setTags(applicationDAO.getAppTags(applicationDTO.getId(), tenantId)); + applicationDTO.setFavourite(applicationDAO.isFavouriteApp(applicationDTO.getId(), userName, tenantId)); if (isFilteringApp(applicationDTO, filter)) { boolean isHideableApp = isHideableApp(applicationDTO.getApplicationReleaseDTOs()); diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java index 0afcc85ab5..45f1320176 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java @@ -362,6 +362,7 @@ public class APIUtil { application.setTags(applicationDTO.getTags()); application.setUnrestrictedRoles(applicationDTO.getUnrestrictedRoles()); application.setRating(applicationDTO.getAppRating()); + application.setFavourite(applicationDTO.isFavourite()); application.setInstallerName(applicationDTO.getApplicationReleaseDTOs().get(0).getInstallerName()); List applicationReleases = new ArrayList<>(); if (ApplicationType.PUBLIC.toString().equals(applicationDTO.getType()) && application.getCategories() diff --git a/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/ApplicationManagementAPI.java b/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/ApplicationManagementAPI.java index eb11be7a40..4eeab57384 100644 --- a/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/ApplicationManagementAPI.java +++ b/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/ApplicationManagementAPI.java @@ -35,8 +35,10 @@ import io.entgra.application.mgt.common.ApplicationList; import javax.validation.Valid; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -70,6 +72,13 @@ import javax.ws.rs.core.Response; key = "perm:app:store:view", roles = {"Internal/devicemgt-user"}, permissions = {"/app-mgt/store/application/view"} + ), + @Scope( + name = "Modify Application", + description = "Modify application state", + key = "perm:app:store:modify", + roles = {"Internal/devicemgt-user"}, + permissions = {"/app-mgt/store/application/modify"} ) } ) @@ -81,6 +90,120 @@ public interface ApplicationManagementAPI { String SCOPE = "scope"; + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Path("/favourite/{appId}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "add application to favourites", + notes = "This will add application to favourites", + tags = "Application Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:store:modify") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully added application to favourites.", + response = ApplicationList.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "Payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while adding the application to favourites.", + response = ErrorResponse.class) + }) + Response addAppToFavourite( + @ApiParam( + name = "appId", + value = "id of the application", + required = true) + @PathParam("appId") int appId); + + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Path("/favourite/{appId}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "DELETE", + value = "remove application from favourites", + notes = "This will removing an application from favourites", + tags = "Application Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:store:modify") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully removed application from favourites.", + response = ApplicationList.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "Payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while removing the application from favourites.", + response = ErrorResponse.class) + }) + Response removeAppFromFavourite( + @ApiParam( + name = "appId", + value = "id of the application", + required = true) + @PathParam("appId") int appId); + + @POST + @Path("/favourite") + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "get all favourite applications", + notes = "This will get all favourite applications", + tags = "Application Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:store:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully got application list.", + response = ApplicationList.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "Application retrieving request payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while getting the application list.", + response = ErrorResponse.class) + }) + Response getFavouriteApplications( + @ApiParam( + name = "filter", + value = "Application filtering data", + required = true) + @Valid Filter filter); + @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) diff --git a/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/impl/ApplicationManagementAPIImpl.java b/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/impl/ApplicationManagementAPIImpl.java index 735df25c92..5f1f124d63 100644 --- a/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/impl/ApplicationManagementAPIImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.store.api/src/main/java/io/entgra/application/mgt/store/api/services/impl/ApplicationManagementAPIImpl.java @@ -28,14 +28,15 @@ import io.entgra.application.mgt.core.exception.NotFoundException; import io.entgra.application.mgt.core.exception.UnexpectedServerErrorException; import io.entgra.application.mgt.core.util.APIUtil; import io.entgra.application.mgt.store.api.services.ApplicationManagementAPI; - import javax.validation.Valid; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; 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; /** @@ -47,30 +48,88 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { private static final Log log = LogFactory.getLog(ApplicationManagementAPIImpl.class); + @POST + @Path("/favourite/{appId}") + @Override + @Consumes(MediaType.APPLICATION_JSON) + public Response addAppToFavourite(@PathParam("appId") int appId) { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + try { + applicationManager.addAppToFavourites(appId); + return Response.status(Response.Status.OK).build(); + } catch (BadRequestException e) { + String msg = "Invalid payload found in the request. Hence verify the request payload."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while adding application to favourites"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @DELETE + @Path("/favourite/{appId}") + @Override + @Consumes(MediaType.APPLICATION_JSON) + public Response removeAppFromFavourite(@PathParam("appId") int appId) { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + try { + applicationManager.removeAppFromFavourites(appId); + return Response.status(Response.Status.OK).build(); + } catch (BadRequestException e) { + String msg = "Invalid payload found in the request. Hence verify the request payload."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while removing application from favourites"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @POST + @Path("/favourite") + @Override + @Consumes(MediaType.APPLICATION_JSON) + public Response getFavouriteApplications(@Valid Filter filter) { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + try { + validateFilter(filter); + ApplicationList applications = applicationManager.getFavouriteApplications(filter); + return Response.status(Response.Status.OK).entity(applications).build(); + } catch (BadRequestException e) { + String msg = "Invalid filter payload found in the request. Hence verify the filter payload."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while retrieving favourite applications"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + @POST @Override @Consumes("application/json") public Response getApplications(@Valid Filter filter) { ApplicationManager applicationManager = APIUtil.getApplicationManager(); try { - if (filter == null) { - String msg = "Request Payload is null"; - log.error(msg); - return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); - } + validateFilter(filter); filter.setAppReleaseState(applicationManager.getInstallableLifecycleState()); ApplicationList applications = applicationManager.getApplications(filter); return Response.status(Response.Status.OK).entity(applications).build(); } catch (BadRequestException e) { - String msg = e.getMessage(); + String msg = "Invalid request payload found in the request. Hence verify the payload."; log.error(msg, e); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } catch (UnexpectedServerErrorException e) { - String msg = e.getMessage(); + String msg = "Unexpected Error occurred while retrieving applications"; log.error(msg); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } catch (ApplicationManagementException e) { - String msg = e.getMessage(); + String msg = "Error occurred while retrieving applications"; + log.error(msg); log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } @@ -101,4 +160,18 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + /** + * This method can be used to check & validate if {@link Filter} object exist. + * + * @param filter {@link Filter} + * @throws BadRequestException if filter object doesn't exist + */ + private void validateFilter(Filter filter) throws BadRequestException { + if (filter == null) { + String msg = "Request Payload is null"; + log.error(msg); + throw new BadRequestException(msg); + } + } } diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml index e20d7cfbf0..63b720a1c1 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml @@ -41,6 +41,7 @@ perm:app:publisher:view perm:app:publisher:update perm:app:store:view + perm:app:store:modify perm:app:subscription:install perm:app:subscription:uninstall perm:admin:app:review:update