From d904fc786956891946e7bd92b559fdb98f62330f Mon Sep 17 00:00:00 2001 From: Dominik Mizyn Date: Wed, 30 Oct 2019 11:41:12 +0100 Subject: [PATCH] UserRolesController methods up readExternalRequestAccess(), getUserAppCatalogRoles(), putAppWithUserRoleRequest(), testGetRoles(), importRolesFromRemoteApplication(), getUsersFromAppEndpoint() up Issue-ID: PORTAL-710 Change-Id: I751d5e412ec85a1a65b0b7d43a023ce6a1915d91 Signed-off-by: Dominik Mizyn --- .../portal/controller/UserRolesController.java | 598 +++++++++++---------- .../onap/portal/dao/ep/EpUserRolesRequestDao.java | 52 ++ .../portal/dao/ep/EpUserRolesRequestDetDao.java | 52 ++ .../java/org/onap/portal/dao/fn/FnRoleDao.java | 5 +- .../portal/domain/db/ep/EpUserRolesRequest.java | 5 + .../java/org/onap/portal/domain/db/fn/FnRole.java | 17 +- .../java/org/onap/portal/domain/db/fn/FnUser.java | 46 ++ .../dto/ecomp/EPUserAppRolesRequestDetail.java | 3 +- .../service/ApplicationsRestClientService.java | 392 ++++++++++++++ .../service/ep/EpUserRolesRequestDetService.java | 62 +++ .../service/ep/EpUserRolesRequestService.java | 62 +++ .../org/onap/portal/service/fn/FnRoleService.java | 8 + .../onap/portal/service/fn/FnUserRoleService.java | 323 ++++++++++- .../src/main/resources/application.properties | 5 +- portal-BE/src/main/resources/test.properties | 3 + .../portal/controller/UserRolesControllerTest.java | 12 + .../portal/service/fn/FnUserRoleServiceTest.java | 78 +++ 17 files changed, 1423 insertions(+), 300 deletions(-) create mode 100644 portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDao.java create mode 100644 portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDetDao.java create mode 100644 portal-BE/src/main/java/org/onap/portal/service/ApplicationsRestClientService.java create mode 100644 portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestDetService.java create mode 100644 portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestService.java create mode 100644 portal-BE/src/test/java/org/onap/portal/service/fn/FnUserRoleServiceTest.java diff --git a/portal-BE/src/main/java/org/onap/portal/controller/UserRolesController.java b/portal-BE/src/main/java/org/onap/portal/controller/UserRolesController.java index fdd1de24..ce7cf1f9 100644 --- a/portal-BE/src/main/java/org/onap/portal/controller/UserRolesController.java +++ b/portal-BE/src/main/java/org/onap/portal/controller/UserRolesController.java @@ -41,14 +41,34 @@ package org.onap.portal.controller; import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.cxf.transport.http.HTTPException; +import org.onap.portal.domain.db.fn.FnRole; import org.onap.portal.domain.db.fn.FnUser; +import org.onap.portal.domain.dto.ecomp.EPUserAppCatalogRoles; +import org.onap.portal.domain.dto.ecomp.ExternalSystemAccess; +import org.onap.portal.domain.dto.transport.AppWithRolesForUser; +import org.onap.portal.domain.dto.transport.FieldsValidator; +import org.onap.portal.domain.dto.transport.UserApplicationRoles; import org.onap.portal.service.AdminRolesService; +import org.onap.portal.service.ApplicationsRestClientService; +import org.onap.portal.service.fn.FnUserRoleService; import org.onap.portal.service.fn.FnUserService; +import org.onap.portal.utils.EcompPortalUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.restful.domain.EcompRole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -58,12 +78,12 @@ public class UserRolesController { private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(UserRolesController.class); private final FnUserService fnUserService; + private final FnUserRoleService fnUserRoleService; private final AdminRolesService adminRolesService; - + private final ApplicationsRestClientService applicationsRestClientService; /* private final UserRolesService userRolesService; - private final ApplicationsRestClientService applicationsRestClientService; private final SearchService searchService;*/ @@ -71,339 +91,343 @@ public class UserRolesController { @Autowired public UserRolesController(final FnUserService fnUserService, - final AdminRolesService adminRolesService) { + FnUserRoleService fnUserRoleService, + final AdminRolesService adminRolesService, + ApplicationsRestClientService applicationsRestClientService) { this.fnUserService = fnUserService; + this.fnUserRoleService = fnUserRoleService; this.adminRolesService = adminRolesService; + this.applicationsRestClientService = applicationsRestClientService; } -/* - @RequestMapping(value = {"/portalApi/queryUsers"}, method = RequestMethod.GET, produces = "application/json") - @PreAuthorize("hasRole('System_Administrator') and hasRole('Account_Administrator')") - public String getPhoneBookSearchResult(Principal principal, @RequestParam("search") String searchString, - HttpServletResponse response) { - FnUser user = fnUserService.loadUserByUsername(principal.getName()); + /* + @RequestMapping(value = {"/portalApi/queryUsers"}, method = RequestMethod.GET, produces = "application/json") + @PreAuthorize("hasRole('System_Administrator') and hasRole('Account_Administrator')") + public String getPhoneBookSearchResult(Principal principal, @RequestParam("search") String searchString, + HttpServletResponse response) { + FnUser user = fnUserService.loadUserByUsername(principal.getName()); - String searchResult = null; - if (!adminRolesService.isSuperAdmin(user) && !adminRolesService.isAccountAdmin(user) - && !adminRolesService.isRoleAdmin(user)) { - EcompPortalUtils.setBadPermissions(user, response, "getPhoneBookSearchResult"); - } else { - searchString = searchString.trim(); - if (searchString.length() > 2) { - searchResult = searchService.searchUsersInPhoneBook(searchString); + String searchResult = null; + if (!adminRolesService.isSuperAdmin(user) && !adminRolesService.isAccountAdmin(user) + && !adminRolesService.isRoleAdmin(user)) { + EcompPortalUtils.setBadPermissions(user, response, "getPhoneBookSearchResult"); } else { - logger.info(EELFLoggerDelegate.errorLogger, - "getPhoneBookSearchResult - too short search string: " + searchString); + searchString = searchString.trim(); + if (searchString.length() > 2) { + searchResult = searchService.searchUsersInPhoneBook(searchString); + } else { + logger.info(EELFLoggerDelegate.errorLogger, + "getPhoneBookSearchResult - too short search string: " + searchString); + } } + EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/queryUsers", "result =", searchResult); + + return searchResult; } - EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/queryUsers", "result =", searchResult); - return searchResult; - } - @RequestMapping(value = {"/portalApi/adminAppsRoles"}, method = { - RequestMethod.GET}, produces = "application/json") - public AppsListWithAdminRole getAppsWithAdminRoleStateForUser(Principal principal, - @RequestParam("user") String orgUserId, HttpServletResponse response) { + @RequestMapping(value = {"/portalApi/adminAppsRoles"}, method = { + RequestMethod.GET}, produces = "application/json") + public AppsListWithAdminRole getAppsWithAdminRoleStateForUser(Principal principal, + @RequestParam("user") String orgUserId, HttpServletResponse response) { - FnUser user = fnUserService.loadUserByUsername(principal.getName()); + FnUser user = fnUserService.loadUserByUsername(principal.getName()); - AppsListWithAdminRole result = null; - if (!adminRolesService.isSuperAdmin(user)) { - EcompPortalUtils.setBadPermissions(user, response, "getAppsWithAdminRoleStateForUser"); - } else { - if (EcompPortalUtils.legitimateUserId(orgUserId)) { - result = adminRolesService.getAppsWithAdminRoleStateForUser(orgUserId); + AppsListWithAdminRole result = null; + if (!adminRolesService.isSuperAdmin(user)) { + EcompPortalUtils.setBadPermissions(user, response, "getAppsWithAdminRoleStateForUser"); } else { - logger.info(EELFLoggerDelegate.errorLogger, - "getAppsWithAdminRoleStateForUser - parms error, no Organization User ID"); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + if (EcompPortalUtils.legitimateUserId(orgUserId)) { + result = adminRolesService.getAppsWithAdminRoleStateForUser(orgUserId); + } else { + logger.info(EELFLoggerDelegate.errorLogger, + "getAppsWithAdminRoleStateForUser - parms error, no Organization User ID"); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + } } - } - StringBuilder adminAppRoles = new StringBuilder(); - if (result != null) { - if (!result.appsRoles.isEmpty()) { - adminAppRoles.append("User '" + result.orgUserId + "' has admin role to the apps = {"); - for (AppNameIdIsAdmin adminAppRole : result.appsRoles) { - if (adminAppRole.isAdmin) { - adminAppRoles.append(adminAppRole.appName + ", "); + StringBuilder adminAppRoles = new StringBuilder(); + if (result != null) { + if (!result.appsRoles.isEmpty()) { + adminAppRoles.append("User '" + result.orgUserId + "' has admin role to the apps = {"); + for (AppNameIdIsAdmin adminAppRole : result.appsRoles) { + if (adminAppRole.isAdmin) { + adminAppRoles.append(adminAppRole.appName + ", "); + } } + adminAppRoles.append("}."); + } else { + adminAppRoles.append("User '" + result.orgUserId + "' has no Apps with Admin Role."); } - adminAppRoles.append("}."); } else { - adminAppRoles.append("User '" + result.orgUserId + "' has no Apps with Admin Role."); + logger.error(EELFLoggerDelegate.errorLogger, + "putAppWithUserRoleStateForUser: getAppsWithAdminRoleStateForUser result is null"); } - } else { - logger.error(EELFLoggerDelegate.errorLogger, - "putAppWithUserRoleStateForUser: getAppsWithAdminRoleStateForUser result is null"); - } - logger.info(EELFLoggerDelegate.errorLogger, adminAppRoles.toString()); + logger.info(EELFLoggerDelegate.errorLogger, adminAppRoles.toString()); - EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/adminAppsRoles", "get result =", result); + EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/adminAppsRoles", "get result =", result); - return result; - } + return result; + } - @RequestMapping(value = {"/portalApi/adminAppsRoles"}, method = { - RequestMethod.PUT}, produces = "application/json") - public FieldsValidator putAppsWithAdminRoleStateForUser(Principal principal, - @RequestBody AppsListWithAdminRole newAppsListWithAdminRoles, HttpServletResponse response) { - - // newAppsListWithAdminRoles.appsRoles - FieldsValidator fieldsValidator = new FieldsValidator(); - StringBuilder newAppRoles = new StringBuilder(); - if (newAppsListWithAdminRoles != null) { - if (!newAppsListWithAdminRoles.appsRoles.isEmpty()) { - newAppRoles - .append("User '" + newAppsListWithAdminRoles.orgUserId - + "' has admin role to the apps = { "); - for (AppNameIdIsAdmin adminAppRole : newAppsListWithAdminRoles.appsRoles) { - if (adminAppRole.isAdmin) { - newAppRoles.append(adminAppRole.appName + " ,"); + @RequestMapping(value = {"/portalApi/adminAppsRoles"}, method = { + RequestMethod.PUT}, produces = "application/json") + public FieldsValidator putAppsWithAdminRoleStateForUser(Principal principal, + @RequestBody AppsListWithAdminRole newAppsListWithAdminRoles, HttpServletResponse response) { + + // newAppsListWithAdminRoles.appsRoles + FieldsValidator fieldsValidator = new FieldsValidator(); + StringBuilder newAppRoles = new StringBuilder(); + if (newAppsListWithAdminRoles != null) { + if (!newAppsListWithAdminRoles.appsRoles.isEmpty()) { + newAppRoles + .append("User '" + newAppsListWithAdminRoles.orgUserId + + "' has admin role to the apps = { "); + for (AppNameIdIsAdmin adminAppRole : newAppsListWithAdminRoles.appsRoles) { + if (adminAppRole.isAdmin) { + newAppRoles.append(adminAppRole.appName + " ,"); + } } + newAppRoles.deleteCharAt(newAppRoles.length() - 1); + newAppRoles.append("}."); + } else { + newAppRoles.append("User '" + newAppsListWithAdminRoles.orgUserId + + "' has no Apps with Admin Role."); } - newAppRoles.deleteCharAt(newAppRoles.length() - 1); - newAppRoles.append("}."); } else { - newAppRoles.append("User '" + newAppsListWithAdminRoles.orgUserId - + "' has no Apps with Admin Role."); + logger.error(EELFLoggerDelegate.errorLogger, + "putAppWithUserRoleStateForUser: putAppsWithAdminRoleStateForUser result is null"); + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } - } else { - logger.error(EELFLoggerDelegate.errorLogger, - "putAppWithUserRoleStateForUser: putAppsWithAdminRoleStateForUser result is null"); - fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - logger.info(EELFLoggerDelegate.errorLogger, newAppRoles.toString()); + logger.info(EELFLoggerDelegate.errorLogger, newAppRoles.toString()); - FnUser user = fnUserService.loadUserByUsername(principal.getName()); + FnUser user = fnUserService.loadUserByUsername(principal.getName()); - boolean changesApplied = false; + boolean changesApplied = false; - if (!adminRolesService.isSuperAdmin(user)) { - EcompPortalUtils.setBadPermissions(user, response, "putAppsWithAdminRoleStateForUser"); - } else { - changesApplied = adminRolesService.setAppsWithAdminRoleStateForUser(newAppsListWithAdminRoles); - AuditLog auditLog = new AuditLog(); - auditLog.setUserId(user.getId()); - auditLog.setActivityCode(EcompAuditLog.CD_ACTIVITY_UPDATE_ACCOUNT_ADMIN); - if (newAppsListWithAdminRoles != null) { - auditLog.setAffectedRecordId(newAppsListWithAdminRoles.orgUserId); - } - auditLog.setComments( - EcompPortalUtils - .truncateString(newAppRoles.toString(), PortalConstants.AUDIT_LOG_COMMENT_SIZE)); - auditService.logActivity(auditLog, null); - - MDC.put(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP, - EPEELFLoggerAdvice.getCurrentDateTimeUTC()); - MDC.put(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP, - EPEELFLoggerAdvice.getCurrentDateTimeUTC()); - EcompPortalUtils.calculateDateTimeDifferenceForLog( - MDC.get(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP), - MDC.get(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP)); - if (newAppsListWithAdminRoles != null) { - logger.info(EELFLoggerDelegate.auditLogger, - EPLogUtil.formatAuditLogMessage( - "UserRolesController.putAppsWithAdminRoleStateForUser", - EcompAuditLog.CD_ACTIVITY_UPDATE_ACCOUNT_ADMIN, user.getOrgUserId(), - newAppsListWithAdminRoles.orgUserId, newAppRoles.toString())); + if (!adminRolesService.isSuperAdmin(user)) { + EcompPortalUtils.setBadPermissions(user, response, "putAppsWithAdminRoleStateForUser"); + } else { + changesApplied = adminRolesService.setAppsWithAdminRoleStateForUser(newAppsListWithAdminRoles); + AuditLog auditLog = new AuditLog(); + auditLog.setUserId(user.getId()); + auditLog.setActivityCode(EcompAuditLog.CD_ACTIVITY_UPDATE_ACCOUNT_ADMIN); + if (newAppsListWithAdminRoles != null) { + auditLog.setAffectedRecordId(newAppsListWithAdminRoles.orgUserId); + } + auditLog.setComments( + EcompPortalUtils + .truncateString(newAppRoles.toString(), PortalConstants.AUDIT_LOG_COMMENT_SIZE)); + auditService.logActivity(auditLog, null); + + MDC.put(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP, + EPEELFLoggerAdvice.getCurrentDateTimeUTC()); + MDC.put(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP, + EPEELFLoggerAdvice.getCurrentDateTimeUTC()); + EcompPortalUtils.calculateDateTimeDifferenceForLog( + MDC.get(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP), + MDC.get(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP)); + if (newAppsListWithAdminRoles != null) { + logger.info(EELFLoggerDelegate.auditLogger, + EPLogUtil.formatAuditLogMessage( + "UserRolesController.putAppsWithAdminRoleStateForUser", + EcompAuditLog.CD_ACTIVITY_UPDATE_ACCOUNT_ADMIN, user.getOrgUserId(), + newAppsListWithAdminRoles.orgUserId, newAppRoles.toString())); + } + MDC.remove(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP); + MDC.remove(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP); + MDC.remove(SystemProperties.MDC_TIMER); } - MDC.remove(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP); - MDC.remove(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP); - MDC.remove(SystemProperties.MDC_TIMER); - } - EcompPortalUtils - .logAndSerializeObject(logger, "/portalApi/adminAppsRoles", "put result =", changesApplied); + EcompPortalUtils + .logAndSerializeObject(logger, "/portalApi/adminAppsRoles", "put result =", changesApplied); - return fieldsValidator; - } + return fieldsValidator; + } - @RequestMapping(value = {"/portalApi/userAppRoles"}, method = { - RequestMethod.GET}, produces = "application/json") - public List getAppRolesForUser(Principal principal, - @RequestParam("user") String orgUserId, - @RequestParam("app") Long appid, @RequestParam("externalRequest") Boolean extRequestValue, - @RequestParam("isSystemUser") Boolean isSystemUser, - HttpServletResponse response) { - FnUser user = fnUserService.loadUserByUsername(principal.getName()); - List result = null; - String feErrorString = ""; - if (!adminRolesService.isAccountAdmin(user) && !adminRolesService.isRoleAdmin(user)) { - logger.debug(EELFLoggerDelegate.debugLogger, - "getAppRolesForUser: Accountadminpermissioncheck {}, RoleAdmincheck {}", - adminRolesService.isAccountAdmin(user), adminRolesService.isRoleAdmin(user)); - EcompPortalUtils.setBadPermissions(user, response, "getAppRolesForUser"); - feErrorString = EcompPortalUtils.getFEErrorString(true, response.getStatus()); - } else { - if ((!isSystemUser && EcompPortalUtils.legitimateUserId(orgUserId)) || isSystemUser) { - result = userRolesService.getAppRolesForUser(appid, orgUserId, extRequestValue, user); - logger.debug(EELFLoggerDelegate.debugLogger, "getAppRolesForUser: result {}, appId {}", - result, appid); - int responseCode = EcompPortalUtils.getExternalAppResponseCode(); - if (responseCode != 0 && responseCode != 200) { - // external error - response.setStatus(responseCode); - feErrorString = EcompPortalUtils.getFEErrorString(false, responseCode); - } else if (result == null) { - // If the result is null, there was an internal onap error - // in the service call. - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - feErrorString = EcompPortalUtils.getFEErrorString(true, - HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } + @RequestMapping(value = {"/portalApi/userAppRoles"}, method = { + RequestMethod.GET}, produces = "application/json") + public List getAppRolesForUser(Principal principal, + @RequestParam("user") String orgUserId, + @RequestParam("app") Long appid, @RequestParam("externalRequest") Boolean extRequestValue, + @RequestParam("isSystemUser") Boolean isSystemUser, + HttpServletResponse response) { + FnUser user = fnUserService.loadUserByUsername(principal.getName()); + List result = null; + String feErrorString = ""; + if (!adminRolesService.isAccountAdmin(user) && !adminRolesService.isRoleAdmin(user)) { + logger.debug(EELFLoggerDelegate.debugLogger, + "getAppRolesForUser: Accountadminpermissioncheck {}, RoleAdmincheck {}", + adminRolesService.isAccountAdmin(user), adminRolesService.isRoleAdmin(user)); + EcompPortalUtils.setBadPermissions(user, response, "getAppRolesForUser"); + feErrorString = EcompPortalUtils.getFEErrorString(true, response.getStatus()); } else { - logger.info(EELFLoggerDelegate.errorLogger, "getAppRolesForUser - no Organization User ID"); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - feErrorString = EcompPortalUtils.getFEErrorString(true, HttpServletResponse.SC_BAD_REQUEST); + if ((!isSystemUser && EcompPortalUtils.legitimateUserId(orgUserId)) || isSystemUser) { + result = userRolesService.getAppRolesForUser(appid, orgUserId, extRequestValue, user); + logger.debug(EELFLoggerDelegate.debugLogger, "getAppRolesForUser: result {}, appId {}", + result, appid); + int responseCode = EcompPortalUtils.getExternalAppResponseCode(); + if (responseCode != 0 && responseCode != 200) { + // external error + response.setStatus(responseCode); + feErrorString = EcompPortalUtils.getFEErrorString(false, responseCode); + } else if (result == null) { + // If the result is null, there was an internal onap error + // in the service call. + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + feErrorString = EcompPortalUtils.getFEErrorString(true, + HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } else { + logger.info(EELFLoggerDelegate.errorLogger, "getAppRolesForUser - no Organization User ID"); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + feErrorString = EcompPortalUtils.getFEErrorString(true, HttpServletResponse.SC_BAD_REQUEST); + } } - } - StringBuilder sbUserApps = new StringBuilder(); - if (result != null && !result.isEmpty()) { - sbUserApps.append("User '" + orgUserId + "' has Roles={"); - for (RoleInAppForUser appRole : result) { - if (appRole.isApplied) { - sbUserApps.append(appRole.roleName + ", "); + StringBuilder sbUserApps = new StringBuilder(); + if (result != null && !result.isEmpty()) { + sbUserApps.append("User '" + orgUserId + "' has Roles={"); + for (RoleInAppForUser appRole : result) { + if (appRole.isApplied) { + sbUserApps.append(appRole.roleName + ", "); + } } + sbUserApps.append("} assigned to the appId '" + appid + "'."); + } else { + // Not sure creating an empty object will make any difference + // but would like to give it a shot for defect #DE221057 + if (result == null) { + result = new ArrayList<>(); + } + sbUserApps.append("User '" + orgUserId + "' and appid " + appid + " has no roles"); } - sbUserApps.append("} assigned to the appId '" + appid + "'."); - } else { - // Not sure creating an empty object will make any difference - // but would like to give it a shot for defect #DE221057 - if (result == null) { - result = new ArrayList<>(); - } - sbUserApps.append("User '" + orgUserId + "' and appid " + appid + " has no roles"); - } - logger.info(EELFLoggerDelegate.errorLogger, sbUserApps.toString()); + logger.info(EELFLoggerDelegate.errorLogger, sbUserApps.toString()); - EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/userAppRoles", "get result =", result); - if (feErrorString != "") { - logger.debug(EELFLoggerDelegate.debugLogger, "LR: FEErrorString to header: " + feErrorString); + EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/userAppRoles", "get result =", result); + if (feErrorString != "") { + logger.debug(EELFLoggerDelegate.debugLogger, "LR: FEErrorString to header: " + feErrorString); - response.addHeader("FEErrorString", feErrorString); - response.addHeader("Access-Control-Expose-Headers", "FEErrorString"); + response.addHeader("FEErrorString", feErrorString); + response.addHeader("Access-Control-Expose-Headers", "FEErrorString"); + } + return result; } - return result; - } - @RequestMapping(value = {"/portalApi/userAppRoles"}, method = { - RequestMethod.PUT}, produces = "application/json") - public PortalRestResponse putAppWithUserRoleStateForUser(Principal principal, - @RequestBody AppWithRolesForUser newAppRolesForUser, HttpServletResponse response) { - // FieldsValidator fieldsValidator = new FieldsValidator(); - PortalRestResponse portalResponse = new PortalRestResponse<>(); - StringBuilder sbUserApps = new StringBuilder(); - if (newAppRolesForUser != null) { - sbUserApps.append("User '" + newAppRolesForUser.getOrgUserId()); - if (newAppRolesForUser.getAppId() != null && !newAppRolesForUser.getAppRoles().isEmpty()) { - sbUserApps.append("' has roles = { "); - for (RoleInAppForUser appRole : newAppRolesForUser.getAppRoles()) { - if (appRole.isApplied) { - sbUserApps.append(appRole.roleName + " ,"); + @RequestMapping(value = {"/portalApi/userAppRoles"}, method = { + RequestMethod.PUT}, produces = "application/json") + public PortalRestResponse putAppWithUserRoleStateForUser(Principal principal, + @RequestBody AppWithRolesForUser newAppRolesForUser, HttpServletResponse response) { + // FieldsValidator fieldsValidator = new FieldsValidator(); + PortalRestResponse portalResponse = new PortalRestResponse<>(); + StringBuilder sbUserApps = new StringBuilder(); + if (newAppRolesForUser != null) { + sbUserApps.append("User '" + newAppRolesForUser.getOrgUserId()); + if (newAppRolesForUser.getAppId() != null && !newAppRolesForUser.getAppRoles().isEmpty()) { + sbUserApps.append("' has roles = { "); + for (RoleInAppForUser appRole : newAppRolesForUser.getAppRoles()) { + if (appRole.isApplied) { + sbUserApps.append(appRole.roleName + " ,"); + } } + sbUserApps.deleteCharAt(sbUserApps.length() - 1); + sbUserApps.append("} assigned for the app " + newAppRolesForUser.getAppId()); + } else { + sbUserApps.append("' has no roles assigned for app " + newAppRolesForUser.getAppId()); } - sbUserApps.deleteCharAt(sbUserApps.length() - 1); - sbUserApps.append("} assigned for the app " + newAppRolesForUser.getAppId()); - } else { - sbUserApps.append("' has no roles assigned for app " + newAppRolesForUser.getAppId()); } - } - logger.info(EELFLoggerDelegate.applicationLogger, "putAppWithUserRoleStateForUser: {}", - sbUserApps.toString()); + logger.info(EELFLoggerDelegate.applicationLogger, "putAppWithUserRoleStateForUser: {}", + sbUserApps.toString()); - FnUser user = fnUserService.loadUserByUsername(principal.getName()); - // boolean changesApplied = false; - ExternalRequestFieldsValidator changesApplied = null; + FnUser user = fnUserService.loadUserByUsername(principal.getName()); + // boolean changesApplied = false; + ExternalRequestFieldsValidator changesApplied = null; - if (!adminRolesService.isAccountAdmin(user) && !adminRolesService.isRoleAdmin(user)) { - EcompPortalUtils.setBadPermissions(user, response, "putAppWithUserRoleStateForUser"); - } else if (newAppRolesForUser == null) { - logger.error(EELFLoggerDelegate.errorLogger, - "putAppWithUserRoleStateForUser: newAppRolesForUser is null"); - } else { - changesApplied = userRolesService.setAppWithUserRoleStateForUser(user, newAppRolesForUser); - try { - if (changesApplied.isResult()) { - logger.info(EELFLoggerDelegate.applicationLogger, - "putAppWithUserRoleStateForUser: succeeded for app {}, user {}", - newAppRolesForUser.getAppId(), - newAppRolesForUser.getAppId()); - - MDC.put(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP, - EPEELFLoggerAdvice.getCurrentDateTimeUTC()); - AuditLog auditLog = new AuditLog(); - auditLog.setUserId(user.getId()); - auditLog.setActivityCode(EcompAuditLog.CD_ACTIVITY_UPDATE_USER); - auditLog.setAffectedRecordId(newAppRolesForUser.getOrgUserId()); - auditLog.setComments(EcompPortalUtils.truncateString(sbUserApps.toString(), - PortalConstants.AUDIT_LOG_COMMENT_SIZE)); - auditService.logActivity(auditLog, null); - - MDC.put(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP, - EPEELFLoggerAdvice.getCurrentDateTimeUTC()); - EcompPortalUtils.calculateDateTimeDifferenceForLog( - MDC.get(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP), - MDC.get(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP)); - logger.info(EELFLoggerDelegate.auditLogger, - EPLogUtil.formatAuditLogMessage( - "UserRolesController.putAppWithUserRoleStateForUser", - EcompAuditLog.CD_ACTIVITY_UPDATE_USER, user.getOrgUserId(), - newAppRolesForUser.getOrgUserId(), sbUserApps.toString())); - MDC.remove(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP); - MDC.remove(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP); - MDC.remove(SystemProperties.MDC_TIMER); - portalResponse = new PortalRestResponse<>(PortalRestStatusEnum.OK, "success", null); + if (!adminRolesService.isAccountAdmin(user) && !adminRolesService.isRoleAdmin(user)) { + EcompPortalUtils.setBadPermissions(user, response, "putAppWithUserRoleStateForUser"); + } else if (newAppRolesForUser == null) { + logger.error(EELFLoggerDelegate.errorLogger, + "putAppWithUserRoleStateForUser: newAppRolesForUser is null"); + } else { + changesApplied = userRolesService.setAppWithUserRoleStateForUser(user, newAppRolesForUser); + try { + if (changesApplied.isResult()) { + logger.info(EELFLoggerDelegate.applicationLogger, + "putAppWithUserRoleStateForUser: succeeded for app {}, user {}", + newAppRolesForUser.getAppId(), + newAppRolesForUser.getAppId()); + + MDC.put(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP, + EPEELFLoggerAdvice.getCurrentDateTimeUTC()); + AuditLog auditLog = new AuditLog(); + auditLog.setUserId(user.getId()); + auditLog.setActivityCode(EcompAuditLog.CD_ACTIVITY_UPDATE_USER); + auditLog.setAffectedRecordId(newAppRolesForUser.getOrgUserId()); + auditLog.setComments(EcompPortalUtils.truncateString(sbUserApps.toString(), + PortalConstants.AUDIT_LOG_COMMENT_SIZE)); + auditService.logActivity(auditLog, null); + + MDC.put(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP, + EPEELFLoggerAdvice.getCurrentDateTimeUTC()); + EcompPortalUtils.calculateDateTimeDifferenceForLog( + MDC.get(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP), + MDC.get(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP)); + logger.info(EELFLoggerDelegate.auditLogger, + EPLogUtil.formatAuditLogMessage( + "UserRolesController.putAppWithUserRoleStateForUser", + EcompAuditLog.CD_ACTIVITY_UPDATE_USER, user.getOrgUserId(), + newAppRolesForUser.getOrgUserId(), sbUserApps.toString())); + MDC.remove(EPCommonSystemProperties.AUDITLOG_BEGIN_TIMESTAMP); + MDC.remove(EPCommonSystemProperties.AUDITLOG_END_TIMESTAMP); + MDC.remove(SystemProperties.MDC_TIMER); + portalResponse = new PortalRestResponse<>(PortalRestStatusEnum.OK, "success", null); - } - if (!changesApplied.isResult()) { - throw new Exception(changesApplied.getDetailMessage()); - } + } + if (!changesApplied.isResult()) { + throw new Exception(changesApplied.getDetailMessage()); + } - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, - "putAppWithUserRoleStateForUser: failed for app {}, user {}", - newAppRolesForUser.getAppId(), - newAppRolesForUser.getOrgUserId(), e); - portalResponse = new PortalRestResponse<>(PortalRestStatusEnum.ERROR, e.getMessage(), null); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, + "putAppWithUserRoleStateForUser: failed for app {}, user {}", + newAppRolesForUser.getAppId(), + newAppRolesForUser.getOrgUserId(), e); + portalResponse = new PortalRestResponse<>(PortalRestStatusEnum.ERROR, e.getMessage(), null); + } } + + EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/userAppRoles", "put result =", changesApplied); + return portalResponse; } - EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/userAppRoles", "put result =", changesApplied); - return portalResponse; - } + @RequestMapping(value = {"/portalApi/updateRemoteUserProfile"}, method = { + RequestMethod.GET}, produces = "application/json") + public PortalRestResponse updateRemoteUserProfile(HttpServletRequest request) { - @RequestMapping(value = {"/portalApi/updateRemoteUserProfile"}, method = { - RequestMethod.GET}, produces = "application/json") - public PortalRestResponse updateRemoteUserProfile(HttpServletRequest request) { + String updateRemoteUserFlag = FAILURE; + try { + // saveNewUser = userService.saveNewUser(newUser); + String orgUserId = request.getParameter("loginId"); + Long appId = Long.parseLong(request.getParameter("appId")); + userRolesService.updateRemoteUserProfile(orgUserId, appId); - String updateRemoteUserFlag = FAILURE; - try { - // saveNewUser = userService.saveNewUser(newUser); - String orgUserId = request.getParameter("loginId"); - Long appId = Long.parseLong(request.getParameter("appId")); - userRolesService.updateRemoteUserProfile(orgUserId, appId); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "updateRemoteUserProfile failed", e); + return new PortalRestResponse<>(PortalRestStatusEnum.OK, updateRemoteUserFlag, e.getMessage()); + } + return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, updateRemoteUserFlag, ""); - } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, "updateRemoteUserProfile failed", e); - return new PortalRestResponse<>(PortalRestStatusEnum.OK, updateRemoteUserFlag, e.getMessage()); } - return new PortalRestResponse<>(PortalRestStatusEnum.ERROR, updateRemoteUserFlag, ""); - - } - + */ @RequestMapping(value = {"/portalApi/app/{appId}/users"}, method = { RequestMethod.GET}, produces = "application/json") - public List getUsersFromAppEndpoint(HttpServletRequest request, - @PathVariable("appId") Long appId) throws HTTPException { + public List getUsersFromAppEndpoint(@PathVariable("appId") Long appId) { try { logger.debug(EELFLoggerDelegate.debugLogger, "/portalApi/app/{}/users was invoked", appId); - return userRolesService.getUsersFromAppEndpoint(appId); + return fnUserRoleService.getUsersFromAppEndpoint(appId); } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "getUsersFromAppEndpoint failed", e); return new ArrayList<>(); @@ -423,21 +447,21 @@ public class UserRolesController { return rolesList; } + @RequestMapping(value = {"/portalApi/admin/import/app/{appId}/roles"}, method = { RequestMethod.GET}, produces = "application/json") - public List importRolesFromRemoteApplication(HttpServletRequest request, - @PathVariable("appId") Long appId) - throws HTTPException { - List rolesList = userRolesService.importRolesFromRemoteApplication(appId); + public List importRolesFromRemoteApplication(@PathVariable("appId") Long appId) throws HTTPException { + List rolesList = fnUserRoleService.importRolesFromRemoteApplication(appId); EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/admin/import/app/{appId}/roles", "response for appId=" + appId, rolesList); return rolesList; } + @RequestMapping(value = {"/portalApi/app/{appId}/user/{orgUserId}/roles"}, method = { RequestMethod.GET}, produces = "application/json") - public EcompRole testGetRoles(HttpServletRequest request, @PathVariable("appId") Long appId, + public EcompRole testGetRoles(@PathVariable("appId") Long appId, @PathVariable("orgUserId") String orgUserId) throws Exception { if (!EcompPortalUtils.legitimateUserId(orgUserId)) { String msg = "Error /user//roles not legitimate orgUserId = " + orgUserId; @@ -458,6 +482,7 @@ public class UserRolesController { return roles[0]; } + @RequestMapping(value = {"/portalApi/saveUserAppRoles"}, method = { RequestMethod.PUT}, produces = "application/json") public FieldsValidator putAppWithUserRoleRequest(Principal principal, @@ -466,8 +491,8 @@ public class UserRolesController { try { FnUser user = fnUserService.loadUserByUsername(principal.getName()); - fieldsValidator = userRolesService.putUserAppRolesRequest(newAppRolesForUser, user); - response.setStatus(fieldsValidator.httpStatusCode.intValue()); + fieldsValidator = fnUserRoleService.putUserAppRolesRequest(newAppRolesForUser, user); + response.setStatus(0); } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "putAppWithUserRoleRequest failed", e); @@ -479,6 +504,7 @@ public class UserRolesController { return fieldsValidator; } + @RequestMapping(value = {"/portalApi/appCatalogRoles"}, method = { RequestMethod.GET}, produces = "application/json") public List getUserAppCatalogRoles(Principal principal, @@ -486,12 +512,12 @@ public class UserRolesController { FnUser user = fnUserService.loadUserByUsername(principal.getName()); List userAppRoleList = null; try { - userAppRoleList = userRolesService.getUserAppCatalogRoles(user, appName); + userAppRoleList = fnUserRoleService.getUserAppCatalogRoles(user, appName); } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "putUserWidgetsSortPref failed", e); } - Collections.sort(userAppRoleList, getUserAppCatalogRolesComparator); + userAppRoleList.sort(getUserAppCatalogRolesComparator); EcompPortalUtils .logAndSerializeObject(logger, "/portalApi/userApplicationRoles", "result =", userAppRoleList); @@ -499,15 +525,16 @@ public class UserRolesController { } + private Comparator getUserAppCatalogRolesComparator = - Comparator.comparing(EPUserAppCatalogRoles::getRolename); + Comparator.comparing(EPUserAppCatalogRoles::getRoleName); @RequestMapping(value = "/portalApi/externalRequestAccessSystem", method = RequestMethod.GET, produces = "application/json") - public ExternalSystemAccess readExternalRequestAccess(HttpServletRequest request) { + public ExternalSystemAccess readExternalRequestAccess() { ExternalSystemAccess result = null; try { - result = userRolesService.getExternalRequestAccess(); + result = fnUserRoleService.getExternalRequestAccess(); EcompPortalUtils .logAndSerializeObject(logger, "/portalApi/externalRequestAccessSystem", "GET result =", result); @@ -516,9 +543,8 @@ public class UserRolesController { "readExternalRequestAccess failed: " + e.getMessage()); } return result; - } -*/ + } @RequestMapping(value = {"/portalApi/checkIfUserIsSuperAdmin"}, method = RequestMethod.GET, produces = "application/json") diff --git a/portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDao.java b/portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDao.java new file mode 100644 index 00000000..b4987e9c --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDao.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * 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. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.dao.ep; + +import org.onap.portal.domain.db.ep.EpUserRolesRequest; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public interface EpUserRolesRequestDao extends JpaRepository { + +} diff --git a/portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDetDao.java b/portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDetDao.java new file mode 100644 index 00000000..35893193 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/dao/ep/EpUserRolesRequestDetDao.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * 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. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.dao.ep; + +import org.onap.portal.domain.db.ep.EpUserRolesRequestDet; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public interface EpUserRolesRequestDetDao extends JpaRepository { + +} diff --git a/portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleDao.java b/portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleDao.java index 66f4758c..01bcdfe5 100644 --- a/portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleDao.java +++ b/portal-BE/src/main/java/org/onap/portal/dao/fn/FnRoleDao.java @@ -53,5 +53,8 @@ import org.springframework.transaction.annotation.Transactional; public interface FnRoleDao extends JpaRepository { @Query - List retrieveAppRoleByAppRoleIdAndByAppId(final @Param("appId") Long appId, final @Param("appRoleId") Long appRoleId); + List retrieveAppRoleByAppRoleIdAndByAppId(final @Param("appId") Long appId, + final @Param("appRoleId") Long appRoleId); + + List getUserRoleOnUserIdAndAppId(final @Param("userId") Long userId, final @Param("appId") Long appId); } diff --git a/portal-BE/src/main/java/org/onap/portal/domain/db/ep/EpUserRolesRequest.java b/portal-BE/src/main/java/org/onap/portal/domain/db/ep/EpUserRolesRequest.java index 52d06b2a..387f038d 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/db/ep/EpUserRolesRequest.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/db/ep/EpUserRolesRequest.java @@ -66,6 +66,7 @@ import lombok.Setter; import org.hibernate.validator.constraints.SafeHtml; import org.onap.portal.domain.db.fn.FnApp; import org.onap.portal.domain.db.fn.FnUser; +import org.onap.portal.domain.dto.ecomp.EPUserAppRolesRequestDetail; /* CREATE TABLE `ep_user_roles_request` ( @@ -123,4 +124,8 @@ public class EpUserRolesRequest implements Serializable { fetch = FetchType.LAZY ) private Set epUserRolesRequestDets; + + public void setEpRequestIdDetail(Set epMyLoginsDetail) { + this.epUserRolesRequestDets = epMyLoginsDetail; + } } diff --git a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnRole.java b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnRole.java index edd843ac..275ce1e3 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnRole.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnRole.java @@ -53,13 +53,10 @@ import javax.persistence.Index; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; -import javax.persistence.NamedNativeQueries; -import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import javax.persistence.Table; -import javax.persistence.UniqueConstraint; import javax.validation.constraints.Digits; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @@ -113,8 +110,18 @@ CREATE TABLE `fn_role` ( name = "FnRole.retrieveActiveRolesOfApplication", query = "from FnRole where active_yn = 'Y' and app_id=:appId"), @NamedQuery(name = "FnRole.retrieveRoleToUpdateInExternalAuthSystem", - query = "FROM FnRole where role_name =:roleName and app_id =:appId") -}) + query = "FROM FnRole where role_name =:roleName and app_id =:appId"), + @NamedQuery( + name = "FnRole.getUserRoleOnUserIdAndAppId", + query = " FROM" + + " FnRole fr,\n" + + " FnUserRole fur\n" + + " WHERE\n" + + " fr.roleId = fur.roleId\n" + + " AND fur.userId = :userId" + + " AND fur.appId = :appId\n" + + " AND fr.activeYn = 'y'") + }) @Table(name = "fn_role", indexes = { @Index(name = "fn_role_name_app_id_idx", columnList = "role_name, app_id", unique = true) diff --git a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnUser.java b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnUser.java index c5a97195..315f911a 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnUser.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnUser.java @@ -44,7 +44,10 @@ import java.io.Serializable; import java.time.LocalDateTime; import java.util.Collection; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; import javax.persistence.CascadeType; import javax.persistence.Column; @@ -82,6 +85,7 @@ import org.onap.portal.domain.db.ep.EpUserNotification; import org.onap.portal.domain.db.ep.EpUserRolesRequest; import org.onap.portal.domain.db.ep.EpWidgetCatalogParameter; import org.onap.portal.domain.dto.DomainVo; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @@ -186,6 +190,8 @@ CREATE TABLE `fn_user` ( @DynamicUpdate public class FnUser extends DomainVo implements UserDetails, Serializable { + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FnUser.class); + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id", nullable = false) @@ -474,4 +480,44 @@ public class FnUser extends DomainVo implements UserDetails, Serializable { return this.firstName + " " + this.lastName; } + public SortedSet getAppEPRoles(FnApp app) { + + logger.debug(EELFLoggerDelegate.debugLogger, "In EPUser.getAppEPRoles() - app = {}", app.getAppName()); + + SortedSet roles = new TreeSet<>(); + Set userAppRoles = getFnUserRoles(); + + logger.debug(EELFLoggerDelegate.debugLogger, "In EPUser.getAppEPRoles() - userApps = {} ", userAppRoles.size()); + + Iterator userAppRolesIterator = userAppRoles.iterator(); + + FnUserRole userAppRole; + // getting default app + while (userAppRolesIterator.hasNext()) { + FnUserRole tempUserApp = userAppRolesIterator.next(); + if (tempUserApp.getAppId().getId().equals(app.getId())) { + + logger.debug(EELFLoggerDelegate.debugLogger, + "In EPUser.getAppEPRoles() - for user {}, found application {}", this.getFullName(), + app.getAppName()); + + userAppRole = tempUserApp; + + FnRole role = userAppRole.getRoleId(); + if (role.getActiveYn()) { + logger.debug(EELFLoggerDelegate.debugLogger, + "In EPUser.getAppEPRoles() - Role {} is active - adding for user {} and app {}", + role.getRoleName(), this.getFullName(), app.getAppName()); + roles.add(role); + } else { + logger.debug(EELFLoggerDelegate.debugLogger, + "In EPUser.getAppEPRoles() - Role {} is NOT active - NOT adding for user {} and app {}", + role.getRoleName(), this.getFullName(), app.getAppName()); + } + } + } + logger.debug(EELFLoggerDelegate.debugLogger, "In EPUser.getAppEPRoles() - roles = {}", roles.size()); + + return roles; + } } diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserAppRolesRequestDetail.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserAppRolesRequestDetail.java index 61e746ae..4d7ead6e 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserAppRolesRequestDetail.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserAppRolesRequestDetail.java @@ -44,6 +44,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.onap.portal.domain.db.ep.EpUserRolesRequest; import org.onap.portal.domain.dto.DomainVo; @Getter @@ -56,6 +57,6 @@ public class EPUserAppRolesRequestDetail extends DomainVo { private Long reqRoleId; private String reqType; - private EPUserAppRolesRequest epRequestIdData; + private EpUserRolesRequest epRequestIdData; } diff --git a/portal-BE/src/main/java/org/onap/portal/service/ApplicationsRestClientService.java b/portal-BE/src/main/java/org/onap/portal/service/ApplicationsRestClientService.java new file mode 100644 index 00000000..e606cb0b --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/service/ApplicationsRestClientService.java @@ -0,0 +1,392 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * 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. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.service; + +import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID; + +import com.google.gson.Gson; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Base64; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.commons.lang.StringUtils; +import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.cxf.jaxrs.impl.ResponseImpl; +import org.apache.cxf.transport.http.HTTPException; +import org.onap.portal.domain.db.fn.FnApp; +import org.onap.portal.logging.aop.EPMetricsLog; +import org.onap.portal.logging.format.EPAppMessagesEnum; +import org.onap.portal.logging.logic.EPLogUtil; +import org.onap.portal.service.fn.old.AppsCacheService; +import org.onap.portal.utils.EPCommonSystemProperties; +import org.onap.portal.utils.EcompPortalUtils; +import org.onap.portal.utils.SystemType; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.onboarding.exception.CipherUtilException; +import org.onap.portalsdk.core.onboarding.util.CipherUtil; +import org.onap.portalsdk.core.util.SystemProperties; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ApplicationsRestClientService { + + private static final String PASSWORD_HEADER = "password"; + private static final String APP_USERNAME_HEADER = "username"; + private static final String BASIC_AUTHENTICATION_HEADER = "Authorization"; + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientService.class); + + Gson gson = null; + + private final AppsCacheService appsCacheService; + + @Autowired + public ApplicationsRestClientService(AppsCacheService appsCacheService) { + this.appsCacheService = appsCacheService; + } + + private static boolean isHttpSuccess(int status) { + return status / 100 == 2; + } + + @EPMetricsLog + private void verifyResponse(Response response, String restPath) throws HTTPException { + int status = response.getStatus(); + logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status); + MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status)); + if (!isHttpSuccess(status)) { + String errMsg = + "Failed. Status=" + status + restPath + "; [" + ((ResponseImpl) response).getStatusInfo() + .getReasonPhrase().toString() + + "]"; + URL url = null; + try { + // must not be null to avoid NPE in HTTPException constructor + url = new URL("http://null"); + if (((ResponseImpl) response).getLocation() != null) { + url = ((ResponseImpl) response).getLocation().toURL(); + } + } catch (MalformedURLException e) { + // never mind. it is only for the debug message. + logger.warn(EELFLoggerDelegate.errorLogger, "Failed to build URL", e); + } + logger.error(EELFLoggerDelegate.errorLogger, + "http response failed. " + restPath + errMsg + "; url=" + url); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError); + throw new HTTPException(status, errMsg, url); + } + } + + private WebClient createClientForApp(long appId, String restPath) { + return createClientFor(appId, restPath, SystemType.APPLICATION); + } + + private static WebClient createClientForPath(String baseUri, String path) { + logger.info(EELFLoggerDelegate.debugLogger, "Creating web client for " + baseUri + " + " + path); + WebClient client = WebClient.create(baseUri); + client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON); + client.path(path); + return client; + } + + //TODO Need to implement the mylogins once the endpoint is confirmed + @EPMetricsLog + private WebClient createClientFor(long appSystemId, String restPath, SystemType type) { + logger.debug(EELFLoggerDelegate.debugLogger, + "creating client for appId=" + appSystemId + "; restPath=" + restPath); + FnApp externalApp = null; + + if (type == SystemType.APPLICATION) { + externalApp = appsCacheService.getApp(appSystemId); + } else { + // TO DO + } + + if (externalApp != null) { + String appBaseUri = (type == SystemType.APPLICATION) ? externalApp.getAppRestEndpoint() : ""; + String username = (type == SystemType.APPLICATION) ? externalApp.getAppUsername() : ""; + String encriptedPwd = (type == SystemType.APPLICATION) ? externalApp.getAppPassword() : ""; + + String appName = (type == SystemType.APPLICATION) ? externalApp.getAppName() : ""; + String decreptedAppPwd = StringUtils.EMPTY; + + // Set local context + MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP); + if (appBaseUri != null && appBaseUri.contains("https")) { + MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS); + } + MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath); + MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName); + MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath); + + if (!encriptedPwd.isEmpty() || encriptedPwd != null || StringUtils.isEmpty(encriptedPwd)) { + try { + decreptedAppPwd = CipherUtil.decryptPKC(encriptedPwd, + SystemProperties.getProperty(SystemProperties.Decryption_Key)); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "createClientFor failed to decrypt", e); + } + } + WebClient client = createClientForPath(appBaseUri, restPath); + + if (externalApp.getAppPassword().isEmpty() || externalApp.getAppPassword() == null) { + logger.debug(EELFLoggerDelegate.debugLogger, + "Entering in the externalApp get app password contains null : {}"); + + externalApp = appsCacheService.getApp(1L); + logger.debug(EELFLoggerDelegate.debugLogger, "external App Information : {}", externalApp); + + String mechidUsername = externalApp.getAppUsername(); + logger.debug(EELFLoggerDelegate.debugLogger, "external App mechidUsername Information : {}", + mechidUsername); + + String password = externalApp.getAppPassword(); + String decreptedexternalAppPwd = StringUtils.EMPTY; + try { + decreptedexternalAppPwd = CipherUtil.decryptPKC(password, + SystemProperties.getProperty(SystemProperties.Decryption_Key)); + } catch (CipherUtilException e) { + logger.error(EELFLoggerDelegate.errorLogger, + "failed to decreptedexternalAppPwd when external app pwd is null", e); + } + + username = mechidUsername; + decreptedAppPwd = decreptedexternalAppPwd; + + } else { + logger.debug(EELFLoggerDelegate.debugLogger, + "Entering in the externalApp get app password is not null : {}"); + + // support basic authentication for some partners + String encoding = Base64.getEncoder() + .encodeToString((username + ":" + decreptedAppPwd).getBytes()); + String encodingStr = "Basic " + encoding; + client.header(BASIC_AUTHENTICATION_HEADER, encodingStr); + } + + // But still keep code downward compatible for non compliant apps + client.header(APP_USERNAME_HEADER, username); + client.header(PASSWORD_HEADER, decreptedAppPwd); + + String encoding = Base64.getEncoder() + .encodeToString((username + ":" + decreptedAppPwd).getBytes()); + String encodingStr = "Basic " + encoding; + client.header(BASIC_AUTHENTICATION_HEADER, encodingStr); + client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID)); + client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE); + logger.debug(EELFLoggerDelegate.debugLogger, + String.format( + "check the partner application URL App %d found, baseUri=[%s], Headers: [%s=%s]", + appSystemId, appBaseUri, + APP_USERNAME_HEADER, username)); + return client; + } + return null; + } + + public T post(Class clazz, long appId, Object payload, String restPath, SystemType type) + throws HTTPException { + WebClient client = null; + Response response = null; + T t = null; + + client = createClientFor(appId, restPath, type); + EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload); + + try { + if (client != null) { + response = client.post(payload); + } else { + logger.error(EELFLoggerDelegate.errorLogger, + "Unable to create the Webclient to make the '" + restPath + "' API call."); + } + } catch (Exception e) { + MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, + Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e); + logger.error(EELFLoggerDelegate.errorLogger, + "Exception occurred while making the POST REST API call", e); + } + + if (response != null) { + //verifyResponse(response); + verifyResponse(response, restPath); + // String contentType = response.getHeaderString("Content-Type"); + if (clazz != null) { + String str = ((ResponseImpl) response).readEntity(String.class); + EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str); + try { + t = (T) gson.fromJson(str, clazz); + + //t = gson.fromJson(str, clazz); + } catch (Exception e) { + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e); + } + } + } + return t; + } + + public T post(Class clazz, long appId, Object payload, String restPath) throws HTTPException { + return post(clazz, appId, payload, restPath, SystemType.APPLICATION); + } + + public T put(Class clazz, long appId, Object payload, String restPath) throws HTTPException { + WebClient client = null; + Response response = null; + T t = null; + + logger.debug(EELFLoggerDelegate.debugLogger, + "Entering to createClientForApp method for payload: {} and restPath: {} and appId: {}", + payload.toString(), restPath, appId); + + client = createClientForApp(appId, restPath); + EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload); + + logger.debug(EELFLoggerDelegate.debugLogger, + "Finished createClientForApp method for payload: {} and restPath: {} and appId: {}", + payload.toString(), restPath, appId); + + try { + if (client != null) { + logger.debug(EELFLoggerDelegate.debugLogger, + "Entering to PUT for payload: {} and restPath: {} and appId: {}", + payload.toString(), restPath, appId); + + response = client.put(payload); + + logger.debug(EELFLoggerDelegate.debugLogger, + "Finished to PUT for payload: {} and restPath: {} and appId: {}", + payload.toString(), restPath, appId); + + } else { + logger.error(EELFLoggerDelegate.errorLogger, + "Unable to create the Webclient to make the '" + restPath + "' API call."); + } + } catch (Exception e) { + MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, + Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e); + logger.error(EELFLoggerDelegate.errorLogger, + "Exception occurred while making the PUT REST API call", e); + } + + if (response != null) { + //verifyResponse(response); + verifyResponse(response, restPath); + String str = ((ResponseImpl) response).readEntity(String.class); + EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str); + try { + t = gson.fromJson(str, clazz); + } catch (Exception e) { + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e); + } + } + return t; + } + + protected Response getResponse(long appId, String restPath) { + WebClient webClient = null; + Response response = null; + + webClient = createClientForApp(appId, restPath); + EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload"); + + try { + if (webClient != null) { + response = webClient.get(); + } else { + logger.error(EELFLoggerDelegate.errorLogger, + "Unable to create the Webclient to make the '" + restPath + "' API call."); + } + } catch (Exception e) { + MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, + Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e); + logger.error(EELFLoggerDelegate.errorLogger, + "Exception occurred while making the GET REST API call", e); + } + return response; + } + + public T get(Class clazz, long appId, String restPath) throws HTTPException { + T t = null; + Response response = getResponse(appId, restPath); + + if (response != null) { + //verifyResponse(response); + verifyResponse(response, restPath); + /* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code, + but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which + doesn't work as expected. Created Portal-253 for tracking */ + String str = ((ResponseImpl) response).readEntity(String.class); + + EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str); + try { + t = gson.fromJson(str, clazz); + } catch (Exception e) { + EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e); + } + } + + return t; + } + + public String getIncomingJsonString(final Long appId, final String restPath) throws HTTPException { + Response response = getResponse(appId, restPath); + + if (response != null) { + //verifyResponse(response); + verifyResponse(response,restPath); + /* It is not recommendable to use the implementation class org.apache.cxf.jaxrs.impl.ResponseImpl in the code, + but had to force this in-order to prevent conflict with the ResponseImpl class of Jersey Client which + doesn't work as expected. Created Portal-253 for tracking */ + String incomingJson = ((ResponseImpl)response).readEntity(String.class); + return incomingJson; + } + + return ""; + } +} diff --git a/portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestDetService.java b/portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestDetService.java new file mode 100644 index 00000000..52e4527f --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestDetService.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * 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. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.service.ep; + +import org.onap.portal.dao.ep.EpUserRolesRequestDetDao; +import org.onap.portal.domain.db.ep.EpUserRolesRequestDet; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class EpUserRolesRequestDetService { + private final EpUserRolesRequestDetDao epUserRolesRequestDetDao; + + @Autowired + public EpUserRolesRequestDetService(EpUserRolesRequestDetDao epUserRolesRequestDetDao) { + this.epUserRolesRequestDetDao = epUserRolesRequestDetDao; + } + + public EpUserRolesRequestDet saveOne(EpUserRolesRequestDet epUserRolesRequestDet){ + return epUserRolesRequestDetDao.save(epUserRolesRequestDet); + } +} diff --git a/portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestService.java b/portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestService.java new file mode 100644 index 00000000..3acd40e9 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/service/ep/EpUserRolesRequestService.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * 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. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.service.ep; + +import org.onap.portal.dao.ep.EpUserRolesRequestDao; +import org.onap.portal.domain.db.ep.EpUserRolesRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class EpUserRolesRequestService { + private final EpUserRolesRequestDao epUserRolesRequestDao; + + @Autowired + public EpUserRolesRequestService(EpUserRolesRequestDao epUserRolesRequestDao) { + this.epUserRolesRequestDao = epUserRolesRequestDao; + } + + public EpUserRolesRequest saveOne(EpUserRolesRequest epUserRolesRequest){ + return epUserRolesRequestDao.save(epUserRolesRequest); + } +} diff --git a/portal-BE/src/main/java/org/onap/portal/service/fn/FnRoleService.java b/portal-BE/src/main/java/org/onap/portal/service/fn/FnRoleService.java index 45867b42..cabefcc3 100644 --- a/portal-BE/src/main/java/org/onap/portal/service/fn/FnRoleService.java +++ b/portal-BE/src/main/java/org/onap/portal/service/fn/FnRoleService.java @@ -84,4 +84,12 @@ public class FnRoleService { } return null; } + + public List retrieveAppRoleByAppRoleIdAndByAppId(Long appId, Long appRoleId){ + return Optional.of(fnRoleDao.retrieveAppRoleByAppRoleIdAndByAppId(appId, appRoleId)).orElse(new ArrayList<>()); + } + + public List getUserRoleOnUserIdAndAppId(final Long userId, final Long appId) { + return Optional.of(fnRoleDao.getUserRoleOnUserIdAndAppId(userId, appId)).orElse(new ArrayList<>()); + } } diff --git a/portal-BE/src/main/java/org/onap/portal/service/fn/FnUserRoleService.java b/portal-BE/src/main/java/org/onap/portal/service/fn/FnUserRoleService.java index 9f136df3..6c1b9fa0 100644 --- a/portal-BE/src/main/java/org/onap/portal/service/fn/FnUserRoleService.java +++ b/portal-BE/src/main/java/org/onap/portal/service/fn/FnUserRoleService.java @@ -40,14 +40,47 @@ package org.onap.portal.service.fn; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.SortedSet; import java.util.stream.Collectors; +import javax.persistence.EntityManager; +import javax.persistence.Tuple; +import javax.servlet.http.HttpServletResponse; +import org.apache.cxf.transport.http.HTTPException; import org.onap.portal.dao.fn.FnUserRoleDao; +import org.onap.portal.domain.db.ep.EpUserRolesRequest; +import org.onap.portal.domain.db.ep.EpUserRolesRequestDet; +import org.onap.portal.domain.db.fn.FnApp; +import org.onap.portal.domain.db.fn.FnRole; +import org.onap.portal.domain.db.fn.FnUser; import org.onap.portal.domain.db.fn.FnUserRole; +import org.onap.portal.domain.dto.ecomp.EPUserAppCatalogRoles; +import org.onap.portal.domain.dto.ecomp.ExternalSystemAccess; +import org.onap.portal.domain.dto.transport.AppWithRolesForUser; +import org.onap.portal.domain.dto.transport.FieldsValidator; +import org.onap.portal.domain.dto.transport.RemoteRole; +import org.onap.portal.domain.dto.transport.RemoteUserWithRoles; +import org.onap.portal.domain.dto.transport.RoleInAppForUser; +import org.onap.portal.domain.dto.transport.UserApplicationRoles; +import org.onap.portal.service.ApplicationsRestClientService; +import org.onap.portal.service.ep.EpUserRolesRequestDetService; +import org.onap.portal.service.ep.EpUserRolesRequestService; +import org.onap.portal.utils.EPCommonSystemProperties; +import org.onap.portal.utils.PortalConstants; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,28 +88,306 @@ import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class FnUserRoleService { + + private static final String USER_APP_CATALOG_ROLES = + "select\n" + + " A.reqId as reqId,\n" + + " B.requestedRoleId.roleId as requestedRoleId,\n" + + " A.requestStatus as requestStatus,\n" + + " A.appId.appId as appId,\n" + + " (\n" + + " select\n" + + " roleName\n" + + " from\n" + + " FnRole\n" + + " where\n" + + " roleId = B.requestedRoleId.roleId\n" + + " ) as roleName\n" + + "from\n" + + " EpUserRolesRequest A\n" + + " left join EpUserRolesRequestDet B on A.reqId = B.reqId.reqId\n" + + "where\n" + + " A.userId.userId = :userid\n" + + " and A.appId IN (\n" + + " select\n" + + " appId\n" + + " from\n" + + " FnApp\n" + + " where\n" + + " appName = :appName\n" + + " )\n" + + " and A.requestStatus = 'P'\n"; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(FnUserRoleService.class); private final FnUserRoleDao fnUserRoleDao; + private final FnAppService fnAppService; + private final FnRoleService fnRoleService; + private final FnUserService fnUserService; + private final EpUserRolesRequestService epUserRolesRequestService; + private final EpUserRolesRequestDetService epUserRolesRequestDetService; + private final EntityManager entityManager; + private final ApplicationsRestClientService applicationsRestClientService; @Autowired - public FnUserRoleService(FnUserRoleDao fnUserRoleDao) { + public FnUserRoleService(FnUserRoleDao fnUserRoleDao, FnAppService fnAppService, + FnRoleService fnRoleService, + FnUserService fnUserService, + EpUserRolesRequestService epUserRolesRequestService, + EpUserRolesRequestDetService epUserRolesRequestDetService, + EntityManager entityManager, + ApplicationsRestClientService applicationsRestClientService) { this.fnUserRoleDao = fnUserRoleDao; + this.fnAppService = fnAppService; + this.fnRoleService = fnRoleService; + this.fnUserService = fnUserService; + this.epUserRolesRequestService = epUserRolesRequestService; + this.epUserRolesRequestDetService = epUserRolesRequestDetService; + this.entityManager = entityManager; + this.applicationsRestClientService = applicationsRestClientService; } public List getAdminUserRoles(final Long userId, final Long roleId, final Long appId) { return fnUserRoleDao.getAdminUserRoles(userId, roleId, appId).orElse(new ArrayList<>()); } - public boolean isSuperAdmin(final String orgUserId, final Long roleId, final Long appId){ - List roles = getUserRolesForRoleIdAndAppId(roleId, appId).stream().filter(role -> role.getUserId().getOrgUserId().equals(orgUserId)).collect(Collectors.toList()); + public boolean isSuperAdmin(final String orgUserId, final Long roleId, final Long appId) { + List roles = getUserRolesForRoleIdAndAppId(roleId, appId).stream() + .filter(role -> role.getUserId().getOrgUserId().equals(orgUserId)).collect(Collectors.toList()); return !roles.isEmpty(); } - private List getUserRolesForRoleIdAndAppId(final Long roleId, final Long appId){ + private List getUserRolesForRoleIdAndAppId(final Long roleId, final Long appId) { return Optional.of(fnUserRoleDao.getUserRolesForRoleIdAndAppId(roleId, appId)).orElse(new ArrayList<>()); } - public FnUserRole saveOne(final FnUserRole fnUserRole){ + public FnUserRole saveOne(final FnUserRole fnUserRole) { return fnUserRoleDao.save(fnUserRole); } + + public ExternalSystemAccess getExternalRequestAccess() { + ExternalSystemAccess res = null; + try { + res = new ExternalSystemAccess(EPCommonSystemProperties.EXTERNAL_ACCESS_ENABLE, + Boolean.parseBoolean( + SystemProperties.getProperty(EPCommonSystemProperties.EXTERNAL_ACCESS_ENABLE))); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "getExternalRequestAccess failed" + e.getMessage()); + } + return res; + } + + public List getUserAppCatalogRoles(FnUser userid, String appName) { + List tuples = entityManager.createQuery(USER_APP_CATALOG_ROLES, Tuple.class) + .setParameter("userid", userid.getUserId()) + .setParameter("appName", appName) + .getResultList(); + return tuples.stream().map(this::tupleToEPUserAppCatalogRoles).collect(Collectors.toList()); + } + + private EPUserAppCatalogRoles tupleToEPUserAppCatalogRoles(Tuple tuple) { + return new EPUserAppCatalogRoles((Long) tuple.get("reqId"), (Long) tuple.get("requestedRoleId"), + (String) tuple.get("roleName"), (String) tuple.get("requestStatus"), (Long) tuple.get("appId")); + } + + private boolean postUserRolesToMylogins(AppWithRolesForUser userAppRolesData, + ApplicationsRestClientService applicationsRestClientService, Long appId, Long userId) + throws JsonProcessingException, HTTPException { + boolean result = false; + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + String userRolesAsString = mapper.writeValueAsString(userAppRolesData); + logger.error(EELFLoggerDelegate.errorLogger, + "Should not be reached here, as the endpoint is not defined yet from the Mylogins"); + applicationsRestClientService.post(AppWithRolesForUser.class, appId, userRolesAsString, + String.format("/user/%s/myLoginroles", userId)); + return result; + } + + public FieldsValidator putUserAppRolesRequest(AppWithRolesForUser newAppRolesForUser, FnUser user) { + FieldsValidator fieldsValidator = new FieldsValidator(); + List appRole; + try { + logger.error(EELFLoggerDelegate.errorLogger, + "Should not be reached here, still the endpoint is yet to be defined"); + boolean result = postUserRolesToMylogins(newAppRolesForUser, applicationsRestClientService, + newAppRolesForUser.getAppId(), user.getId()); + logger.debug(EELFLoggerDelegate.debugLogger, "putUserAppRolesRequest: result {}", result); + FnApp app = fnAppService.getById(newAppRolesForUser.getAppId()); + EpUserRolesRequest epUserRolesRequest = new EpUserRolesRequest(); + epUserRolesRequest.setCreatedDate(LocalDateTime.now()); + epUserRolesRequest.setUpdatedDate(LocalDateTime.now()); + epUserRolesRequest.setUserId(user); + epUserRolesRequest.setAppId(app); + epUserRolesRequest.setRequestStatus("P"); + List appRoleIdList = newAppRolesForUser.getAppRoles(); + Set appRoleDetails = new LinkedHashSet<>(); + epUserRolesRequestService.saveOne(epUserRolesRequest); + for (RoleInAppForUser userAppRoles : appRoleIdList) { + Boolean isAppliedVal = userAppRoles.getIsApplied(); + if (isAppliedVal) { + appRole = fnRoleService + .retrieveAppRoleByAppRoleIdAndByAppId(newAppRolesForUser.getAppId(), + userAppRoles.getRoleId()); + if (!appRole.isEmpty()) { + EpUserRolesRequestDet epAppRoleDetail = new EpUserRolesRequestDet(); + epAppRoleDetail.setRequestedRoleId(appRole.get(0)); + epAppRoleDetail.setRequestType("P"); + epAppRoleDetail.setReqId(epUserRolesRequest); + epUserRolesRequestDetService.saveOne(epAppRoleDetail); + } + } + } + epUserRolesRequest.setEpRequestIdDetail(appRoleDetails); + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_OK); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "putUserAppRolesRequest failed", e); + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + return fieldsValidator; + } + + public List importRolesFromRemoteApplication(Long appId) throws HTTPException { + FnRole[] appRolesFull = applicationsRestClientService.get(FnRole[].class, appId, "/rolesFull"); + List rolesList = Arrays.asList(appRolesFull); + for (FnRole externalAppRole : rolesList) { + + // Try to find an existing extern role for the app in the local + // onap DB. If so, then use its id to update the existing external + // application role record. + Long externAppId = externalAppRole.getId(); + FnRole existingAppRole = fnRoleService.getRole(appId, externAppId); + if (existingAppRole != null) { + logger.debug(EELFLoggerDelegate.debugLogger, + String.format( + "ecomp role already exists for app=%s; appRoleId=%s. No need to import this one.", + appId, externAppId)); + continue; + } + // persistExternalRoleInEcompDb(externalAppRole, appId, + // roleService); + } + + return rolesList; + } + + public List getUsersFromAppEndpoint(Long appId) throws HTTPException { + ArrayList userApplicationRoles = new ArrayList<>(); + + FnApp app = fnAppService.getById(appId); + //If local or centralized application + if (PortalConstants.PORTAL_APP_ID.equals(appId) || app.getAuthCentral()) { + List userList = fnUserService.getActiveUsers(); + for (FnUser user : userList) { + UserApplicationRoles userWithAppRoles = convertToUserApplicationRoles(appId, user, app); + if (userWithAppRoles.getRoles() != null && userWithAppRoles.getRoles().size() > 0) { + userApplicationRoles.add(userWithAppRoles); + } + } + + } + // remote app + else { + RemoteUserWithRoles[] remoteUsers = null; + String remoteUsersString = applicationsRestClientService.getIncomingJsonString(appId, "/users"); + + remoteUsers = doGetUsers(isAppUpgradeVersion(app), remoteUsersString); + + userApplicationRoles = new ArrayList<>(); + for (RemoteUserWithRoles remoteUser : remoteUsers) { + UserApplicationRoles userWithRemoteAppRoles = convertToUserApplicationRoles(appId, + remoteUser); + if (userWithRemoteAppRoles.getRoles() != null + && userWithRemoteAppRoles.getRoles().size() > 0) { + userApplicationRoles.add(userWithRemoteAppRoles); + } else { + logger.debug(EELFLoggerDelegate.debugLogger, + "User " + userWithRemoteAppRoles.getOrgUserId() + + " doesn't have any roles assigned to any app."); + } + } + } + + return userApplicationRoles; + } + + private UserApplicationRoles convertToUserApplicationRoles(Long appId, RemoteUserWithRoles remoteUser) { + UserApplicationRoles userWithRemoteAppRoles = new UserApplicationRoles(); + userWithRemoteAppRoles.setAppId(appId); + userWithRemoteAppRoles.setOrgUserId(remoteUser.getOrgUserId()); + userWithRemoteAppRoles.setFirstName(remoteUser.getFirstName()); + userWithRemoteAppRoles.setLastName(remoteUser.getLastName()); + userWithRemoteAppRoles.setRoles(remoteUser.getRoles()); + return userWithRemoteAppRoles; + } + + private boolean isAppUpgradeVersion(FnApp app) { + return true; + } + + private RemoteUserWithRoles[] doGetUsers(boolean postOpenSource, String remoteUsersString) { + + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(remoteUsersString, RemoteUserWithRoles[].class); + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, + "doGetUsers : Failed : Unexpected property in incoming JSON", + e); + logger.error(EELFLoggerDelegate.errorLogger, + "doGetUsers : Incoming JSON that caused it --> " + remoteUsersString); + } + + return new RemoteUserWithRoles[0]; + } + + private UserApplicationRoles convertToUserApplicationRoles(Long appId, FnUser user, FnApp app) { + UserApplicationRoles userWithRemoteAppRoles = new UserApplicationRoles(); + userWithRemoteAppRoles.setAppId(appId); + userWithRemoteAppRoles.setOrgUserId(user.getOrgUserId()); + userWithRemoteAppRoles.setFirstName(user.getFirstName()); + userWithRemoteAppRoles.setLastName(user.getLastName()); + userWithRemoteAppRoles.setRoles(convertToRemoteRoleList(user, app)); + return userWithRemoteAppRoles; + } + + private List convertToRemoteRoleList(FnUser user, FnApp app) { + List roleList = new ArrayList<>(); + SortedSet roleSet = user.getAppEPRoles(app); + for (FnRole role : roleSet) { + logger.debug(EELFLoggerDelegate.debugLogger, "In convertToRemoteRoleList() - for user {}, found Name {}", user.getOrgUserId(), role.getRoleName()); + RemoteRole rRole = new RemoteRole(); + rRole.setId(role.getId()); + rRole.setName(role.getRoleName()); + roleList.add(rRole); + } + + //Get the active roles of user for that application using query + List userEpRoleList = fnRoleService.getUserRoleOnUserIdAndAppId(user.getId(), app.getId()); + + for (FnRole remoteUserRoleList : userEpRoleList) { + + RemoteRole remoteRoleListId = roleList.stream().filter(x -> remoteUserRoleList.getId().equals(x.getId())) + .findAny().orElse(null); + if (remoteRoleListId == null) { + logger.debug(EELFLoggerDelegate.debugLogger, + "Adding the role to the rolelist () - for user {}, found Name {}", user.getOrgUserId(), + + remoteUserRoleList.getRoleName()); + RemoteRole role = new RemoteRole(); + role.setId(remoteUserRoleList.getId()); + role.setName(remoteUserRoleList.getRoleName()); + + roleList.add(role); + } + + } + + logger.debug(EELFLoggerDelegate.debugLogger, "rolelist size of the USER() - for user {}, found RoleListSize {}", user.getOrgUserId(), roleList.size()); + + return roleList; + + + + } } diff --git a/portal-BE/src/main/resources/application.properties b/portal-BE/src/main/resources/application.properties index 56e0f04d..eff7141c 100644 --- a/portal-BE/src/main/resources/application.properties +++ b/portal-BE/src/main/resources/application.properties @@ -29,4 +29,7 @@ log4j.logger.org.hibernate=info # SQL statements and parameters log4j.logger.org.hibernate.SQL=debug -log4j.logger.org.hibernate.type.descriptor.sql=trace \ No newline at end of file +log4j.logger.org.hibernate.type.descriptor.sql=trace + +#PROPERTIES +external_access_enable = false \ No newline at end of file diff --git a/portal-BE/src/main/resources/test.properties b/portal-BE/src/main/resources/test.properties index bdc23f7c..64639b44 100644 --- a/portal-BE/src/main/resources/test.properties +++ b/portal-BE/src/main/resources/test.properties @@ -10,3 +10,6 @@ spring.datasource.username=sa spring.datasource.password=password spring.datasource.initialization-mode=always spring.jpa.database-platform=org.hibernate.dialect.H2Dialect + +#PROPERTIES +external_access_enable = false \ No newline at end of file diff --git a/portal-BE/src/test/java/org/onap/portal/controller/UserRolesControllerTest.java b/portal-BE/src/test/java/org/onap/portal/controller/UserRolesControllerTest.java index b2048e8f..dcbef08a 100644 --- a/portal-BE/src/test/java/org/onap/portal/controller/UserRolesControllerTest.java +++ b/portal-BE/src/test/java/org/onap/portal/controller/UserRolesControllerTest.java @@ -54,6 +54,7 @@ import java.util.HashSet; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; +import javax.servlet.http.HttpServletRequest; import javax.sql.DataSource; import org.h2.tools.RunScript; import org.hibernate.Session; @@ -68,6 +69,8 @@ import org.onap.portal.domain.db.fn.FnLanguage; import org.onap.portal.domain.db.fn.FnRole; import org.onap.portal.domain.db.fn.FnUser; import org.onap.portal.domain.db.fn.FnUserRole; +import org.onap.portal.domain.dto.ecomp.ExternalSystemAccess; +import org.onap.portal.framework.MockitoTestSuite; import org.onap.portal.service.fn.FnAppService; import org.onap.portal.service.fn.FnLanguageService; import org.onap.portal.service.fn.FnLuTimezoneService; @@ -127,4 +130,13 @@ class UserRolesControllerTest { //Then assertEquals(expected, actual); } + + @Test + void readExternalRequestAccess() { + ExternalSystemAccess expected = new ExternalSystemAccess("external_access_enable", false); + ExternalSystemAccess actual = userRolesController.readExternalRequestAccess(); + + assertEquals(expected.getAccessValue(), actual.getAccessValue()); + assertEquals(expected.getKey(), actual.getKey()); + } } \ No newline at end of file diff --git a/portal-BE/src/test/java/org/onap/portal/service/fn/FnUserRoleServiceTest.java b/portal-BE/src/test/java/org/onap/portal/service/fn/FnUserRoleServiceTest.java new file mode 100644 index 00000000..bdbc2c03 --- /dev/null +++ b/portal-BE/src/test/java/org/onap/portal/service/fn/FnUserRoleServiceTest.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * 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. + * + * ============LICENSE_END============================================ + * + * + */ + +package org.onap.portal.service.fn; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import javax.transaction.Transactional; +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.onap.portal.domain.db.fn.FnUser; +import org.onap.portal.domain.dto.ecomp.EPUserAppCatalogRoles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +@Transactional +@TestPropertySource(locations = "classpath:test.properties") +class FnUserRoleServiceTest { + @Autowired + private FnUserRoleService fnUserRoleService; + @Autowired + private FnUserService fnUserService; + + @Test + void getUserAppCatalogRoles() { + FnUser user = fnUserService.loadUserByUsername("demo"); + + List actual = fnUserRoleService.getUserAppCatalogRoles(user, "appName"); + + List expected = new ArrayList<>(); + + assertEquals(expected, actual); + } +} \ No newline at end of file -- 2.16.6