/*- * ================================================================================ * eCOMP Portal * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ================================================================================ */ package org.openecomp.portalapp.portal.service; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Base64; /*- * ================================================================================ * eCOMP Portal * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ================================================================================ */ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiConstants; import org.openecomp.portalsdk.core.onboarding.crossapi.PortalApiProperties; import org.openecomp.portalsdk.core.onboarding.ueb.Helper; import org.openecomp.portalsdk.core.onboarding.ueb.TopicManager; import org.openecomp.portalsdk.core.service.DataAccessService; import org.openecomp.portalsdk.core.util.CipherUtil; import org.openecomp.portalsdk.core.util.SystemProperties; import org.openecomp.portalapp.portal.domain.AdminUserApp; import org.openecomp.portalapp.portal.domain.AdminUserApplications; import org.openecomp.portalapp.portal.domain.AppIdAndNameTransportModel; import org.openecomp.portalapp.portal.domain.AppsResponse; import org.openecomp.portalapp.portal.domain.EPApp; import org.openecomp.portalapp.portal.domain.EPUser; import org.openecomp.portalapp.portal.domain.EcompApp; import org.openecomp.portalapp.portal.domain.UserRole; import org.openecomp.portalapp.portal.domain.UserRoles; import org.openecomp.portalapp.portal.logging.aop.EPMetricsLog; import org.openecomp.portalapp.portal.logging.format.EPAppMessagesEnum; import org.openecomp.portalapp.portal.logging.logic.EPLogUtil; import org.openecomp.portalapp.portal.transport.FieldsValidator; import org.openecomp.portalapp.portal.transport.FunctionalMenuItem; import org.openecomp.portalapp.portal.transport.LocalRole; import org.openecomp.portalapp.portal.transport.OnboardingApp; import org.openecomp.portalapp.portal.ueb.EPUebHelper; import org.openecomp.portalapp.portal.utils.EPSystemProperties; import org.openecomp.portalapp.portal.utils.EcompPortalUtils; import org.openecomp.portalapp.portal.ecomp.model.AppCatalogItem; import com.att.nsa.apiClient.http.HttpException; import com.att.nsa.cambria.client.CambriaClient.CambriaApiException; import com.att.nsa.cambria.client.CambriaClientBuilders; import com.att.nsa.cambria.client.CambriaIdentityManager; @Service("epAppService") @Transactional @org.springframework.context.annotation.Configuration @EnableAspectJAutoProxy @EPMetricsLog public class EPAppServiceImpl implements EPAppService { private String ECOMP_APP_ID = "1"; private String SUPER_ADMIN_ROLE_ID = "1"; private String ACCOUNT_ADMIN_ROLE_ID = "999"; private String RESTRICTED_APP_ROLE_ID = "900"; private static final String PATH_SEPARATOR = "/"; private static final String webappsBaseFullPath = System.getProperty("catalina.base") + PATH_SEPARATOR + "wtpwebapps"; private static final String imageCacheRelativePath = "images" + PATH_SEPARATOR + "cache"; private String ecompportalPath = null; private static final Long DUBLICATED_FIELD_VALUE_ECOMP_ERROR = new Long( EPSystemProperties.DUBLICATED_FIELD_VALUE_ECOMP_ERROR); private static final String urlField = "url"; private static final String nameField = "name"; EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(EPAppServiceImpl.class); @Autowired AdminRolesService adminRolesService; @Autowired private SessionFactory sessionFactory; @Autowired private DataAccessService dataAccessService; @Autowired EPUebHelper epUebHelper; private String constructImagesCachePath() { String filePath = System.getProperty("catalina.base"); File eclipseWebAppDir = new File(webappsBaseFullPath); if (eclipseWebAppDir.exists()) { // Eclipse webapps filePath += PATH_SEPARATOR + "wtpwebapps"; } else { filePath += PATH_SEPARATOR + "webapps"; } filePath += PATH_SEPARATOR + SystemProperties.getProperty(EPSystemProperties.ECOMP_CONTEXT_ROOT);; return filePath.toString(); // return SystemProperties.getProperty(SystemProperties.TEMP_PATH); } @PostConstruct private void init() { ecompportalPath = constructImagesCachePath(); writeAppsImagesToDiskCacheIfNecessary(); SUPER_ADMIN_ROLE_ID = SystemProperties.getProperty(EPSystemProperties.SYS_ADMIN_ROLE_ID); ACCOUNT_ADMIN_ROLE_ID = SystemProperties.getProperty(EPSystemProperties.ACCOUNT_ADMIN_ROLE_ID); ECOMP_APP_ID = SystemProperties.getProperty(EPSystemProperties.ECOMP_APP_ID); RESTRICTED_APP_ROLE_ID = SystemProperties.getProperty(EPSystemProperties.RESTRICTED_APP_ROLE_ID); } @Override public List getUserAsAdminApps(EPUser user) { if (adminRolesService.isAccountAdmin(user)) { String sql = "SELECT * FROM FN_APP join FN_USER_ROLE ON FN_USER_ROLE.APP_ID=FN_APP.APP_ID where " + "FN_USER_ROLE.USER_ID=" + user.getId() + " AND FN_USER_ROLE.ROLE_ID=" + ACCOUNT_ADMIN_ROLE_ID + " AND FN_APP.ENABLED = 'Y'"; logQuery(sql); try { @SuppressWarnings("unchecked") List adminApps = dataAccessService.executeSQLQuery(sql, EPApp.class, null); return adminApps; } catch (Exception e) { EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); return null; } } else { logger.error(EELFLoggerDelegate.errorLogger, "getUserAsAdminApps: only Account Admin may invoke this function!"); return new ArrayList(); } } @Override public List getUserByOrgUserIdAsAdminApps(String orgUserId) { String format = "SELECT * FROM FN_APP app INNER JOIN FN_USER_ROLE userrole ON userrole.APP_ID=app.APP_ID " + "INNER JOIN FN_USER user on user.USER_ID = userrole.USER_ID " + "WHERE user.ORG_USER_ID = '%s' AND userrole.ROLE_ID=" + ACCOUNT_ADMIN_ROLE_ID + " AND FN_APP.ENABLED = 'Y'"; String sql = String.format(format, orgUserId); logQuery(sql); try { @SuppressWarnings("unchecked") List adminApps = dataAccessService.executeSQLQuery(sql, EPApp.class, null); return adminApps; } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, EcompPortalUtils.getStackTrace(e)); EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); return null; } } @Override public List getAppsFullList() { @SuppressWarnings("unchecked") List apps = dataAccessService.getList(EPApp.class, null); // Write the image to disk in case if it is missing for (EPApp app : apps) writeAppImageToDiskCacheIfNecessary(app); return apps; } @Override public List getEcompAppAppsFullList() { return transformAppsToEcompApps(getAppsFullList()); } @Override public List transformAppsToEcompApps(List appsList) { List ecompAppList = new ArrayList(); for (EPApp app : appsList) { EcompApp ecompApp = new EcompApp(); ecompApp.setId(app.getId()); ecompApp.setName(app.getName()); ecompApp.setImageUrl(app.getImageUrl()); ecompApp.setDescription(app.getDescription()); ecompApp.setNotes(app.getNotes()); ecompApp.setUrl(app.getUrl()); ecompApp.setAlternateUrl(app.getAlternateUrl()); ecompApp.setUebTopicName(app.getUebTopicName()); ecompApp.setUebKey(app.getUebKey()); ecompApp.setUebSecret(app.getUebSecret()); ecompApp.setEnabled(app.getEnabled()); ecompApp.setRestrictedApp(app.isRestrictedApp()); ecompAppList.add(ecompApp); } return ecompAppList; } @Override public EPApp getApp(Long appId) { try { @SuppressWarnings("unchecked") List apps = dataAccessService.getList(EPApp.class, " where id = " + appId, null, null); return (apps.size() > 0) ? apps.get(0) : null; } catch (Exception e) { EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); return null; } } @SuppressWarnings("unchecked") @Override public List getAdminApps(EPUser user) { if (adminRolesService.isAccountAdmin(user)) { String format = "SELECT app.APP_ID, app.APP_NAME, app.APP_TYPE FROM FN_APP app inner join FN_USER_ROLE userrole ON userrole.APP_ID=app.APP_ID " + "where userrole.USER_ID = %d AND userrole.ROLE_ID=" + ACCOUNT_ADMIN_ROLE_ID + " AND app.ENABLED = 'Y'"; String sql = String.format(format, user.getId()); // sql += " AND app.APP_REST_ENDPOINT IS NOT NULL AND // app.APP_REST_ENDPOINT <> ''"; logQuery(sql); try { return (ArrayList) dataAccessService.executeSQLQuery(sql, AppIdAndNameTransportModel.class, null); } catch (Exception e) { EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while fetching the adminApps for user " + user.getLoginId() + ". Details: " + EcompPortalUtils.getStackTrace(e)); } } return new ArrayList(); } @SuppressWarnings("unchecked") @Override public List getAppsForSuperAdminAndAccountAdmin(EPUser user) { if (adminRolesService.isSuperAdmin(user) || adminRolesService.isAccountAdmin(user)) { String format = ""; String sql = ""; if (adminRolesService.isSuperAdmin(user)) { format = "SELECT app.APP_ID, app.APP_NAME, app.APP_TYPE FROM FN_APP app " + "where app.ENABLED = 'Y'"; } else { format = "SELECT app.APP_ID, app.APP_NAME, APP_TYPE FROM FN_APP app inner join FN_USER_ROLE userrole ON userrole.APP_ID=app.APP_ID " + "where userrole.USER_ID = %d AND userrole.ROLE_ID=" + ACCOUNT_ADMIN_ROLE_ID + " AND app.ENABLED = 'Y'"; } sql = String.format(format, user.getId()); // sql += " AND app.APP_REST_ENDPOINT IS NOT NULL AND // app.APP_REST_ENDPOINT <> ''"; logQuery(sql); try { return (ArrayList) dataAccessService.executeSQLQuery(sql, AppIdAndNameTransportModel.class, null); } catch (Exception e) { EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while fetching the adminApps for user " + user.getLoginId() + ". Details: " + EcompPortalUtils.getStackTrace(e)); } } return new ArrayList(); } private void logQuery(String sql) { logger.debug(EELFLoggerDelegate.debugLogger, "Executing query: " + sql); } public DataAccessService getDataAccessService() { return dataAccessService; } public void setDataAccessService(DataAccessService dataAccessService) { this.dataAccessService = dataAccessService; } @Override public List getAppsAdmins() { String sql = "SELECT apps.APP_NAME, apps.APP_ID, user.USER_ID, user.FIRST_NAME, user.LAST_NAME, user.ORG_USER_ID FROM fn_user_role userrole " + "INNER JOIN fn_user user ON user.USER_ID = userrole.USER_ID " + "INNER JOIN fn_app apps ON apps.APP_ID = userrole.APP_ID " + "WHERE userrole.ROLE_ID = " + ACCOUNT_ADMIN_ROLE_ID + " AND apps.ENABLED = 'Y'"; logQuery(sql); try { @SuppressWarnings("unchecked") List adminApps = dataAccessService.executeSQLQuery(sql, AdminUserApp.class, null); // DataAccessService // does // not // use // generic // types. return aggregateRowsResultsByUserId(adminApps); } catch (Exception e) { EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); return null; } } private List aggregateRowsResultsByUserId(List adminApps) { HashMap adminUserApplications = new HashMap(); for (AdminUserApp app : adminApps) { Long userId = app.getUser_Id(); if (adminUserApplications.get(userId) == null) adminUserApplications.put(userId, new AdminUserApplications(app)); else adminUserApplications.get(userId).addApp(app.getAppId(), app.getAppName()); } return new ArrayList(adminUserApplications.values()); } @Override public List getAllApps(Boolean all) { // If all is true, return both active and inactive apps. Otherwise, just // active apps. @SuppressWarnings("unchecked") // Sort the list by application name so the drop-down looks pretty. List apps = all ? (List) dataAccessService.getList(EPApp.class, " where id != " + ECOMP_APP_ID, "name", null) : (List) dataAccessService.getList(EPApp.class, " where enabled = 'Y'", "name", null); List appsModified = new ArrayList(); for (EPApp app : apps) { appsModified.add(new AppsResponse(app.getId(), app.getName(), app.isRestrictedApp(), app.getEnabled())); // Write the image to disk in case if it is missing writeAppImageToDiskCacheIfNecessary(app); } return appsModified; } @Override public UserRoles getUserProfile(String loginId) { String format = "SELECT DISTINCT user.USER_ID, role.ROLE_ID, user.ORG_USER_ID, user.FIRST_NAME, user.LAST_NAME, role.ROLE_NAME FROM fn_user_role userrole " + "INNER JOIN fn_user user ON user.USER_ID = userrole.USER_ID " + "INNER JOIN fn_role role ON role.ROLE_ID = userrole.ROLE_ID " + "WHERE user.ORG_USER_ID = \"%s\";"; String sql = String.format(format, loginId); logQuery(sql); @SuppressWarnings("unchecked") List userRoleList = dataAccessService.executeSQLQuery(sql, UserRole.class, null); ArrayList usersRolesList = aggregateUserProfileRowsResultsByRole(userRoleList); if (usersRolesList == null || usersRolesList.size() < 1) return null; return usersRolesList.get(0); } private ArrayList aggregateUserProfileRowsResultsByRole(List userRoleList) { HashMap userRoles = new HashMap(); for (UserRole user : userRoleList) { String orgUserId = user.getOrgUserId(); if (userRoles.get(orgUserId) == null) userRoles.put(orgUserId, new UserRoles(user)); else userRoles.get(orgUserId).addRole(user.getRoleId()); } return new ArrayList(userRoles.values()); } private boolean isRestrictedApp(Long appId) { EPApp app = getApp(appId); return app.isRestrictedApp(); } // For the functional menu edit @Override public List getAppRoles(Long appId) { String sql = ""; if (isRestrictedApp(appId)) { sql = "SELECT ROLE_ID, ROLE_NAME from FN_ROLE where ROLE_ID = '" + RESTRICTED_APP_ROLE_ID + "'"; } else { sql = "SELECT ROLE_ID, ROLE_NAME from FN_ROLE where APP_ID = '" + appId + "'"; } logQuery(sql); @SuppressWarnings("unchecked") List appRoles = dataAccessService.executeSQLQuery(sql, LocalRole.class, null); return appRoles; } private String userAppsQuery(EPUser user) { StringBuilder query = new StringBuilder(); if (adminRolesService.isSuperAdmin(user)) { query.append("SELECT * FROM FN_APP where FN_APP.ENABLED = 'Y'"); } else { query.append("SELECT * FROM FN_APP join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = FN_APP.APP_ID where "); query.append( "FN_USER_ROLE.USER_ID = " + user.getId() + " AND FN_USER_ROLE.ROLE_ID != " + SUPER_ADMIN_ROLE_ID); query.append(" AND FN_APP.ENABLED = 'Y'"); } return query.toString(); } @Override public List getUserApps(EPUser user) { List openApps = getOpenApps(); for (EPApp app : openApps) { // Write the image to disk in case if it is missing writeAppImageToDiskCacheIfNecessary(app); } if (user.isGuest()) { return openApps; } else { String sql = userAppsQuery(user); logQuery(sql); TreeSet distinctApps = new TreeSet(); @SuppressWarnings("unchecked") List adminApps = dataAccessService.executeSQLQuery(sql, EPApp.class, null); for (EPApp app : adminApps) { // Write the image to disk in case if it is missing writeAppImageToDiskCacheIfNecessary(app); distinctApps.add(app); } for (EPApp app : openApps) { distinctApps.add(app); } List userApps = new ArrayList(); userApps.addAll(distinctApps); return userApps; } } @Override public List getPersAdminApps(EPUser user) { final Map params = new HashMap<>(); params.put("userId", user.getId()); // Named query is stored in EP.hbm.xml, mapped to EPApp @SuppressWarnings("unchecked") List list = dataAccessService.executeNamedQuery("getPersAdminApps", params, null); // Why is this necessary? for (EPApp app : list) writeAppImageToDiskCacheIfNecessary(app); return list; } @Override public List getPersUserApps(EPUser user) { final Map params = new HashMap<>(); params.put("userId", user.getId()); // Named query is stored in EP.hbm.xml, mapped to EPApp @SuppressWarnings("unchecked") List list = dataAccessService.executeNamedQuery("getPersUserApps", params, null); // Why is this necessary? for (EPApp app : list) writeAppImageToDiskCacheIfNecessary(app); return list; } /* * (non-Javadoc) * @see org.openecomp.portalapp.portal.service.EPAppService#getAppCatalog(org.openecomp.portalapp.portal.domain.EPUser) */ @Override public List getUserAppCatalog(EPUser user) { final Map params = new HashMap<>(); params.put("userId", user.getId()); // Named query is stored in EP.hbm.xml, mapped to AppCatalogItem @SuppressWarnings("unchecked") List list = dataAccessService.executeNamedQuery("getUserAppCatalog", params, null); return list; } /* * (non-Javadoc) * @see org.openecomp.portalapp.portal.service.EPAppService#getAdminAppCatalog(org.openecomp.portalapp.portal.domain.EPUser) */ @Override public List getAdminAppCatalog(EPUser user) { final Map params = new HashMap<>(); params.put("userId", user.getId()); // Named query is stored in EP.hbm.xml, mapped to AppCatalogItem @SuppressWarnings("unchecked") List list = dataAccessService.executeNamedQuery("getAdminAppCatalog", params, null); return list; } private List getOpenApps() { @SuppressWarnings("unchecked") List openApps = dataAccessService.getList(EPApp.class, " where open='Y' and enabled='Y'", null, null); return openApps; } @Override public List getOnboardingApps() { @SuppressWarnings("unchecked") List apps = (List) dataAccessService.getList(EPApp.class, " where id!=" + ECOMP_APP_ID, null, null); List onboardingAppsList = new ArrayList(); for (EPApp app : apps) { OnboardingApp onboardingApp = new OnboardingApp(); createOnboardingFromApp(app, onboardingApp); onboardingAppsList.add(onboardingApp); } return onboardingAppsList; } @Override public List getEnabledNonOpenOnboardingApps() { @SuppressWarnings("unchecked") List apps = (List) dataAccessService.getList(EPApp.class, " where enabled = true and open = false and id!=" + ECOMP_APP_ID, null, null); List onboardingAppsList = new ArrayList(); for (EPApp app : apps) { OnboardingApp onboardingApp = new OnboardingApp(); createOnboardingFromApp(app, onboardingApp); onboardingAppsList.add(onboardingApp); } return onboardingAppsList; } private FieldsValidator onboardingAppFieldsChecker(OnboardingApp onboardingApp) { FieldsValidator fieldsValidator = new FieldsValidator(); if (onboardingApp.name == null || onboardingApp.name.length() == 0 || onboardingApp.url == null || onboardingApp.url.length() == 0 || onboardingApp.restrictedApp == null || onboardingApp.isOpen == null || onboardingApp.isEnabled == null || (onboardingApp.id != null && onboardingApp.id.equals(ECOMP_APP_ID)) // For a normal app (appType==1), these fields must be filled // in. // For a restricted app (appType==2), they will be empty. || ((!onboardingApp.restrictedApp) && (onboardingApp.username == null || onboardingApp.username.length() == 0 || onboardingApp.appPassword == null || onboardingApp.appPassword.length() == 0))) { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_BAD_REQUEST); } return fieldsValidator; } @SuppressWarnings("unchecked") private void validateOnboardingApp(OnboardingApp onboardingApp, FieldsValidator fieldsValidator) { boolean dublicatedUrl = false; boolean dublicatedName = false; List apps; if (onboardingApp.id == null) { apps = dataAccessService.getList(EPApp.class, " where url = '" + onboardingApp.url + "' or name = '" + onboardingApp.name + "'", null, null); } else { apps = dataAccessService.getList(EPApp.class, " where id = " + onboardingApp.id + " or url = '" + onboardingApp.url + "' or name = '" + onboardingApp.name + "'", null, null); } for (EPApp app : apps) { if (onboardingApp.id != null && onboardingApp.id.equals(app.getId())) { continue; } if (!dublicatedUrl && app.getUrl().equalsIgnoreCase(onboardingApp.url)) { dublicatedUrl = true; if (dublicatedName) { break; } } if (!dublicatedName && app.getName().equalsIgnoreCase(onboardingApp.name)) { dublicatedName = true; if (dublicatedUrl) { break; } } } if (dublicatedUrl || dublicatedName) { if (dublicatedUrl) { fieldsValidator.addProblematicFieldName(urlField); } if (dublicatedName) { fieldsValidator.addProblematicFieldName(nameField); } fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_CONFLICT); fieldsValidator.errorCode = DUBLICATED_FIELD_VALUE_ECOMP_ERROR; } } @Override public FieldsValidator modifyOnboardingApp(OnboardingApp modifiedOnboardingApp, EPUser user) { logger.debug(EELFLoggerDelegate.debugLogger, "LR: entering modifyOnboardingApp"); FieldsValidator fieldsValidator = onboardingAppFieldsChecker(modifiedOnboardingApp); if (fieldsValidator.httpStatusCode.intValue() == HttpServletResponse.SC_OK) { validateOnboardingApp(modifiedOnboardingApp, fieldsValidator); } if (fieldsValidator.httpStatusCode.intValue() == HttpServletResponse.SC_OK) { if (modifiedOnboardingApp.id != null) { updateApp(modifiedOnboardingApp.id, modifiedOnboardingApp, fieldsValidator, user); } else { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_BAD_REQUEST); } } return fieldsValidator; } @Override public FieldsValidator addOnboardingApp(OnboardingApp newOnboardingApp, EPUser user) { FieldsValidator fieldsValidator = onboardingAppFieldsChecker(newOnboardingApp); if (fieldsValidator.httpStatusCode.intValue() == HttpServletResponse.SC_OK) { validateOnboardingApp(newOnboardingApp, fieldsValidator); } if (fieldsValidator.httpStatusCode.intValue() == HttpServletResponse.SC_OK) { if (newOnboardingApp.id == null) { updateApp(null, newOnboardingApp, fieldsValidator, user); } else { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_BAD_REQUEST); } } return fieldsValidator; } @Override public FieldsValidator deleteOnboardingApp(EPUser user, Long appid) { FieldsValidator fieldsValidator = new FieldsValidator(); if (!adminRolesService.isSuperAdmin(user)) { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_FORBIDDEN); return fieldsValidator; } Boolean result = false; Session localSession = null; Transaction transaction = null; try { localSession = sessionFactory.openSession(); transaction = localSession.beginTransaction(); // 1) Remove the URL for any functional menu item associated with // this app String sql = "UPDATE fn_menu_functional m, fn_menu_functional_roles mr SET m.url='' " + " WHERE m.menu_id=mr.menu_id " + " AND mr.app_id='" + appid + "'"; logQuery(sql); Query query = localSession.createSQLQuery(sql); query.executeUpdate(); // 2) Remove any favorites associated with a menu item that is // associated with this app sql = "Delete from fn_menu_favorites " + " using fn_menu_favorites inner join fn_menu_functional_roles " + " where fn_menu_functional_roles.app_id='" + appid + "' " + " AND fn_menu_functional_roles.menu_id=fn_menu_favorites.menu_id"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); // 3) Remove all role,appid records from fn_menu_functional_role // that are associated with this app sql = "delete from fn_menu_functional_roles where app_id='" + appid + "'"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); // 4) Remove all records from fn_user_role associated with this app sql = "delete from fn_user_role where app_id='" + appid + "'"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); // 5) Remove all records from fn_role associated with this app sql = "delete from fn_role where app_id='" + appid + "'"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); // 6) Remove any widgets associated with this app sql = "delete from fn_widget where app_id='" + appid + "'"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); // Remove any selections in the personalization table sql = "delete from fn_pers_user_app_sel where app_id='" + appid + "'"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); // Delete the app sql = "delete from fn_app where app_id='" + appid + "'"; logQuery(sql); query = localSession.createSQLQuery(sql); query.executeUpdate(); transaction.commit(); result = true; } catch (Exception e) { EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); EcompPortalUtils.rollbackTransaction(transaction, "deleteOnboardingApp rollback, exception = " + e); } finally { EcompPortalUtils.closeLocalSession(localSession, "deleteOnboardingApp"); } if (!result) { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } return fieldsValidator; } private static Object syncRests = new Object(); // An app has been enabled/disabled. Must enable/disable all associated // functional menu items. private void setFunctionalMenuItemsEnabled(Session localSession, Boolean enabled, Long appId) { String active_yn = enabled ? "Y" : "N"; String sql = "SELECT m.menu_id, m.column_num, m.text, m.parent_menu_id, m.url, m.active_yn " + "FROM fn_menu_functional m, fn_menu_functional_roles r " + "WHERE m.menu_id = r.menu_id " + " AND r.app_id = '" + appId + "' "; logQuery(sql); @SuppressWarnings("unchecked") List menuItems = dataAccessService.executeSQLQuery(sql, FunctionalMenuItem.class, null); for (FunctionalMenuItem menuItem : menuItems) { FunctionalMenuItem myMenuItem = (FunctionalMenuItem) localSession.get(FunctionalMenuItem.class, menuItem.menuId); myMenuItem.active_yn = active_yn; localSession.save(myMenuItem); } } // Attention! If (appId == null) we use this function to create application // otherwise we use it to modify existing application private void updateApp(Long appId, OnboardingApp onboardingApp, FieldsValidator fieldsValidator, EPUser user) { logger.debug(EELFLoggerDelegate.debugLogger, "LR: entering updateApp"); // Separate out the code for a restricted app, since it doesn't need any // of the UEB code. if (onboardingApp.restrictedApp) { boolean result = false; Session localSession = null; Transaction transaction = null; try { localSession = sessionFactory.openSession(); transaction = localSession.beginTransaction(); EPApp app; if (appId == null) { app = new EPApp(); } else { app = (EPApp) localSession.get(EPApp.class, appId); if (app == null || app.getId() == null) { // App is already // deleted! transaction.commit(); localSession.close(); fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_NOT_FOUND); return; } } createAppFromOnboarding(app, onboardingApp, localSession); localSession.saveOrUpdate(app); // Enable or disable all menu items associated with this app setFunctionalMenuItemsEnabled(localSession, onboardingApp.isEnabled, appId); transaction.commit(); result = true; } catch (Exception e) { EcompPortalUtils.rollbackTransaction(transaction, "updateApp rollback, exception = " + EcompPortalUtils.getStackTrace(e)); } finally { EcompPortalUtils.closeLocalSession(localSession, "updateApp"); } if (!result) { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } else { synchronized (syncRests) { boolean result = false; Session localSession = null; Transaction transaction = null; try { localSession = sessionFactory.openSession(); transaction = localSession.beginTransaction(); EPApp app; if (appId == null) { app = new EPApp(); // ------------------------------------------------------------------------------------------- // Register this App with the UEB communication server. // Save // the App's unique mailbox/topic // name and keys to the FN_APP table. The App's mailbox // and // keys will be visible to the // admin on the ECOMP portal. // ------------------------------------------------------------------------------------------- TopicManager topicManager = new TopicManager(); final CambriaIdentityManager im = new CambriaClientBuilders.IdentityManagerBuilder() .usingHosts(Helper.uebUrlList()).build(); com.att.nsa.apiClient.credentials.ApiCredential credential = im.createApiKey(user.getEmail(), "ECOMP Portal Owner"); String appKey = credential.getApiKey(); String appSecret = credential.getApiSecret(); boolean isProductionBuild = EcompPortalUtils.isProductionBuild(); String appMailboxName = null; int maxNumAttemptsToCreateATopic = 3; boolean successfullyCreatedMailbox = false; for (int i = 0; i < maxNumAttemptsToCreateATopic; i++) { if (isProductionBuild) { appMailboxName = "ECOMP-PORTAL-OUTBOX-" + (int) (Math.random() * 100000.0); } else { appMailboxName = "ECOMP-PORTAL-OUTBOX-TEST-" + (int) (Math.random() * 100000.0); } try { topicManager.createTopic( PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY), PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_SECRET), appMailboxName, "ECOMP outbox for app" + onboardingApp.name); successfullyCreatedMailbox = true; logger.debug(EELFLoggerDelegate.debugLogger, "Successfully created " + appMailboxName + " for App " + onboardingApp.name); logger.debug(EELFLoggerDelegate.debugLogger, " Key = " + appKey + " Secret = " + appSecret + " generated using = " + user.getEmail()); break; } catch (HttpException e) { String stackTrace = EcompPortalUtils.getStackTrace(e); EPLogUtil.logEcompError(EPAppMessagesEnum.BeUebConnectionError, e.getMessage()); if (e.getStatusCode() == 409) { logger.error(EELFLoggerDelegate.errorLogger, "Topic/mailbox " + appMailboxName + " already exists. Will try using a different name, Details: " + stackTrace); } else { logger.error(EELFLoggerDelegate.errorLogger, "HttpException when onboarding App: " + stackTrace); } } } if (successfullyCreatedMailbox) { onboardingApp.setUebTopicName(appMailboxName); onboardingApp.setUebKey(appKey); onboardingApp.setUebSecret(appSecret); try { /* * EP is a publisher to this App's new mailbox */ topicManager.addPublisher( PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY), PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_SECRET), PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY), appMailboxName); /* * This App is a subcriber of it's own mailbox */ topicManager.addSubscriber( PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY), PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_SECRET), appKey, appMailboxName); /* * This App is a publisher to EP */ topicManager.addPublisher( PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY), PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_SECRET), appKey, PortalApiProperties.getProperty(PortalApiConstants.ECOMP_PORTAL_INBOX_NAME)); } catch (HttpException | CambriaApiException | IOException e) { String stackTrace = EcompPortalUtils.getStackTrace(e); EPLogUtil.logEcompError(EPAppMessagesEnum.BeUebRegisterOnboardingAppError, e.getMessage()); logger.error(EELFLoggerDelegate.errorLogger, "Error when configuring Publisher/Subscriber for App's new mailbox " + stackTrace); transaction.commit(); localSession.close(); fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_CONFLICT); return; } } else { transaction.commit(); localSession.close(); fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_CONFLICT); return; } } else { app = (EPApp) localSession.get(EPApp.class, appId); if (app == null || app.getId() == null) { // App is // already // deleted! transaction.commit(); localSession.close(); fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_NOT_FOUND); return; } } logger.debug(EELFLoggerDelegate.debugLogger, "LR: about to call createAppFromOnboarding"); createAppFromOnboarding(app, onboardingApp, localSession); logger.debug(EELFLoggerDelegate.debugLogger, "LR: updateApp: finished calling createAppFromOnboarding"); localSession.saveOrUpdate(app); logger.debug(EELFLoggerDelegate.debugLogger, "LR: updateApp: finished calling localSession.saveOrUpdate"); // Enable or disable all menu items associated with this app setFunctionalMenuItemsEnabled(localSession, onboardingApp.isEnabled, appId); logger.debug(EELFLoggerDelegate.debugLogger, "LR: updateApp: finished calling setFunctionalMenuItemsEnabled"); transaction.commit(); logger.debug(EELFLoggerDelegate.debugLogger, "LR: updateApp: finished calling transaction.commit"); epUebHelper.addPublisher(app); logger.debug(EELFLoggerDelegate.debugLogger, "LR: updateApp: finished calling epUebHelper.addPublisher"); result = true; } catch (Exception e) { logger.debug(EELFLoggerDelegate.debugLogger, "exception: " + e.toString()); logger.debug(EELFLoggerDelegate.debugLogger, "exception.cause: " + e.getCause()); EPLogUtil.logEcompError(EPAppMessagesEnum.BeUebRegisterOnboardingAppError, e.getMessage()); EPLogUtil.logEcompError(EPAppMessagesEnum.BeDaoSystemError); EcompPortalUtils.rollbackTransaction(transaction, "updateApp rollback, exception = " + EcompPortalUtils.getStackTrace(e)); } finally { EcompPortalUtils.closeLocalSession(localSession, "updateApp"); } if (!result) { fieldsValidator.httpStatusCode = new Long(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } } } private void createOnboardingFromApp(EPApp app, OnboardingApp onboardingApp) { onboardingApp.id = app.getId(); onboardingApp.name = app.getName(); onboardingApp.imageUrl = app.getImageUrl(); onboardingApp.description = app.getDescription(); onboardingApp.notes = app.getNotes(); onboardingApp.url = app.getUrl(); onboardingApp.alternateUrl = app.getAlternateUrl(); onboardingApp.restUrl = app.getAppRestEndpoint(); onboardingApp.isOpen = app.getOpen(); onboardingApp.isEnabled = app.getEnabled(); onboardingApp.username = app.getUsername(); onboardingApp.appPassword = this.decryptedPassword(app.getAppPassword(), app); onboardingApp.uebTopicName = app.getUebTopicName(); onboardingApp.uebKey = app.getUebKey(); onboardingApp.uebSecret = app.getUebSecret(); onboardingApp.setRestrictedApp(app.isRestrictedApp()); if (app.getThumbnail() != null) { onboardingApp.thumbnail = new String(Base64.getEncoder().encode(app.getThumbnail())); // Write the image to disk in case if it is missing writeAppImageToDiskCacheIfNecessary(app); } } private EPApp createAppFromOnboarding(EPApp app, OnboardingApp onboardingApp, Session localSession) { logger.debug(EELFLoggerDelegate.debugLogger, "LR: entering createAppFromOnboarding"); app.setName(onboardingApp.name); app.setDescription(onboardingApp.description); app.setNotes(onboardingApp.notes); app.setUrl(onboardingApp.url); app.setAlternateUrl(onboardingApp.alternateUrl); app.setAppRestEndpoint(onboardingApp.restUrl); app.setOpen(onboardingApp.isOpen); app.setEnabled(onboardingApp.isEnabled); app.setUsername(onboardingApp.username); app.setAppPassword(this.encryptedPassword(onboardingApp.appPassword, app)); app.setUebTopicName(onboardingApp.uebTopicName); app.setUebKey(onboardingApp.uebKey); app.setUebSecret(onboardingApp.uebSecret); app.setRestrictedApp(onboardingApp.restrictedApp); if (!StringUtils.isEmpty(onboardingApp.thumbnail)) { logger.debug(EELFLoggerDelegate.debugLogger, "LR: onboarding thumbnail is NOT empty"); String[] splitBase64Thumbnail = onboardingApp.thumbnail.split("base64,"); if (splitBase64Thumbnail != null) { logger.debug(EELFLoggerDelegate.debugLogger, "LR: length of splitBase64Thumbnail: " + splitBase64Thumbnail.length); } if (splitBase64Thumbnail.length > 1) { // This occurs when we have a new image, not an existing image byte[] decodedImage = Base64.getDecoder().decode(splitBase64Thumbnail[1].getBytes()); logger.debug(EELFLoggerDelegate.debugLogger, "LR: finished calling decode"); deleteOldImageFromDisk(app); saveNewImageToDisk(app, onboardingApp, decodedImage); app.setThumbnail(decodedImage); } } else if (app.getThumbnail() != null) { // The thumbnail that came in from the json is empty; the previous // thumbnail is NOT empty. Must delete it. logger.debug(EELFLoggerDelegate.debugLogger, "LR: onboarding thumbnail is empty; db thumbnail is NOT null"); deleteOldImageFromDisk(app); app.setThumbnail(null); } else { logger.debug(EELFLoggerDelegate.debugLogger, "LR: onboarding thumbnail is empty; db thumbnail is null"); } return app; } private void deleteOldImageFromDisk(EPApp app) { if (app.getImageUrl() != null) { String oldImageFullFilePath = ecompportalPath + PATH_SEPARATOR + app.getImageUrl(); try { File oldFile = new File(oldImageFullFilePath); if (oldFile.exists() && oldFile.delete()) { app.setImageUrl(null); logger.debug(EELFLoggerDelegate.debugLogger, "old file " + oldImageFullFilePath + " was successfully deleted"); } } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "old file " + oldImageFullFilePath + " delete failure", EcompPortalUtils.getStackTrace(e)); } } } // No need to optimize this code since it happens only when adding/modifying // an application. private void saveNewImageToDisk(EPApp app, OnboardingApp onboardingApp, byte[] decodedImage) { // Notice!!! // using separator did not worked on WINDOWS as the database was saved // as assets\images\tmp\ which the UI did not understand thus ichanged // it to "/" String imageFileName = constructImageName(onboardingApp); String imageRelativeFilePath = imageCacheRelativePath + PATH_SEPARATOR + imageFileName; String imageFullFilePath = ecompportalPath + PATH_SEPARATOR + imageRelativeFilePath; logger.debug(EELFLoggerDelegate.debugLogger, "saving app " + onboardingApp.name + " image to " + imageFullFilePath); FileOutputStream osf = null; try { // Base64 Image example: 'data:image/png;base64,AAAFBfj42Pj4' logger.info(EELFLoggerDelegate.debugLogger, "Saving new image: " + decodedImage); osf = writeImageAsBase64(decodedImage, imageFullFilePath); app.setImageUrl(imageRelativeFilePath); logger.debug(EELFLoggerDelegate.debugLogger, "saveBlobImageToDisk onboardingAppImageUrl = " + imageRelativeFilePath); } catch (IOException e) { logger.error(EELFLoggerDelegate.errorLogger, "failed to save image to " + imageFullFilePath, EcompPortalUtils.getStackTrace(e)); } finally { if (osf != null) { try { osf.close(); } catch (IOException e) { logger.error(EELFLoggerDelegate.errorLogger, "failed to close outpoot stream for image " + imageFullFilePath, EcompPortalUtils.getStackTrace(e)); } } } } private FileOutputStream writeImageAsBase64(byte[] decodedImage, String imageFullFilePath) throws FileNotFoundException, IOException { FileOutputStream osf; File of = new File(imageFullFilePath); osf = new FileOutputStream(of); osf.write(decodedImage); osf.flush(); return osf; } private String constructImageName(OnboardingApp onboardingApp) { return "portal" + String.valueOf(onboardingApp.url.hashCode() + "_" + (int) (Math.random() * 100000.0)) + ".png"; } // Don't encrypt or decrypt the password if it is null or the empty string private String decryptedPassword(String encryptedAppPwd, EPApp app) { String result = ""; if (encryptedAppPwd != null & encryptedAppPwd.length() > 0) { try { result = CipherUtil.decrypt(encryptedAppPwd, SystemProperties.getProperty(SystemProperties.Decryption_Key)); } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "Unable to decrypt, App name = " + app.getName(), EcompPortalUtils.getStackTrace(e)); } } return result; } private String encryptedPassword(String decryptedAppPwd, EPApp app) { String result = ""; if (decryptedAppPwd != null & decryptedAppPwd.length() > 0) { try { result = CipherUtil.encrypt(decryptedAppPwd, SystemProperties.getProperty(SystemProperties.Decryption_Key)); } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger, "Unable to encrypt, App name = " + app, EcompPortalUtils.getStackTrace(e)); } } return result; } public void writeAppsImagesToDiskCacheIfNecessary() { List apps = getAppsFullList(); for (EPApp app : apps) { String imageFullFilePath = ecompportalPath + PATH_SEPARATOR + app.getImageUrl(); File f = new File(imageFullFilePath); if (f.exists() && !f.isDirectory()) { continue;// logger.debug("verified existence."); } if (app.getThumbnail() == null) { logger.debug(EELFLoggerDelegate.debugLogger, "no thumbnail blob available for this app, cannot write to disk " + app.getName()); continue; } FileOutputStream osf = null; try { logger.info(EELFLoggerDelegate.debugLogger, "Rewriting image for " + app.getName() + " from db to: " + imageFullFilePath); osf = writeImageAsBase64(app.getThumbnail(), imageFullFilePath); logger.debug(EELFLoggerDelegate.debugLogger, "missing, wrote to disk."); } catch (IOException e) { logger.error(EELFLoggerDelegate.errorLogger, "failed to save image to " + imageFullFilePath, EcompPortalUtils.getStackTrace(e)); } finally { try { if (osf != null) osf.close(); } catch (IOException e) { logger.error(EELFLoggerDelegate.errorLogger, "writeAppsImagesToDiskCacheIfNecessary: failed to close output stream for image " + imageFullFilePath, EcompPortalUtils.getStackTrace(e)); } } } } private void writeAppImageToDiskCacheIfNecessary(EPApp app) { if (app == null || app.getImageUrl() == null) { return; } String imageFullFilePath = ecompportalPath + PATH_SEPARATOR + app.getImageUrl(); File f = new File(imageFullFilePath); // Image file if (f.exists() && !f.isDirectory()) { return;// logger.debug("verified existence."); } if (app.getThumbnail() == null) { logger.debug(EELFLoggerDelegate.debugLogger, "no thumbnail blob available for this app, cannot write to disk " + app.getName()); return; } FileOutputStream osf = null; try { logger.info(EELFLoggerDelegate.debugLogger, "Rewriting image for " + app.getName() + " from db to: " + imageFullFilePath); osf = writeImageAsBase64(app.getThumbnail(), imageFullFilePath); logger.debug(EELFLoggerDelegate.debugLogger, "missing, wrote to disk."); } catch (IOException e) { logger.error(EELFLoggerDelegate.errorLogger, "failed to save image to " + imageFullFilePath, EcompPortalUtils.getStackTrace(e)); } finally { try { if (osf != null) osf.close(); } catch (IOException e) { logger.error(EELFLoggerDelegate.errorLogger, "writeAppsImagesToDiskCacheIfNecessary: failed to close output stream for image " + imageFullFilePath, EcompPortalUtils.getStackTrace(e)); } } } @Override public List getUserRemoteApps(String id) { StringBuilder query = new StringBuilder(); query.append("SELECT * FROM FN_APP join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = FN_APP.APP_ID where "); query.append( "FN_USER_ROLE.USER_ID = " + id + " AND FN_USER_ROLE.ROLE_ID != " + SUPER_ADMIN_ROLE_ID); query.append(" AND FN_APP.ENABLED = 'Y'"); TreeSet distinctApps = new TreeSet(); @SuppressWarnings("unchecked") List adminApps = dataAccessService.executeSQLQuery(query.toString(), EPApp.class, null); for (EPApp app : adminApps) { // Write the image to disk in case if it is missing writeAppImageToDiskCacheIfNecessary(app); distinctApps.add(app); } List userApps = new ArrayList(); userApps.addAll(distinctApps); return userApps; } }