diff options
8 files changed, 387 insertions, 48 deletions
diff --git a/portal-BE/src/main/java/org/onap/portal/controller/WidgetsController.java b/portal-BE/src/main/java/org/onap/portal/controller/WidgetsController.java index 7b4bbea0..e40efe11 100644 --- a/portal-BE/src/main/java/org/onap/portal/controller/WidgetsController.java +++ b/portal-BE/src/main/java/org/onap/portal/controller/WidgetsController.java @@ -45,14 +45,19 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.onap.portal.domain.db.fn.FnUser; +import org.onap.portal.domain.dto.transport.FieldsValidator; import org.onap.portal.domain.dto.transport.OnboardingWidget; +import org.onap.portal.service.AdminRolesService; import org.onap.portal.service.WidgetService; import org.onap.portal.service.fn.FnUserService; import org.onap.portal.utils.EcompPortalUtils; +import org.onap.portal.validation.DataValidator; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; +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.RestController; @@ -65,11 +70,16 @@ public class WidgetsController { private final FnUserService fnUserService; private final WidgetService widgetService; + private final AdminRolesService adminRolesService; + private final DataValidator dataValidator; @Autowired - public WidgetsController(FnUserService fnUserService, WidgetService widgetService) { + public WidgetsController(FnUserService fnUserService, WidgetService widgetService, + AdminRolesService adminRolesService, DataValidator dataValidator) { this.fnUserService = fnUserService; this.widgetService = widgetService; + this.adminRolesService = adminRolesService; + this.dataValidator = dataValidator; } @RequestMapping(value = { "/portalApi/widgets" }, method = RequestMethod.GET, produces = "application/json") @@ -92,4 +102,37 @@ public class WidgetsController { EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/widgets", "GET result =", response.getStatus()); return onboardingWidgets; } + + @RequestMapping(value = { "/portalApi/widgets/{widgetId}" }, method = { RequestMethod.PUT }, produces = "application/json") + public FieldsValidator putOnboardingWidget(Principal principal, HttpServletRequest request, @PathVariable("widgetId") Long widgetId, + @RequestBody OnboardingWidget onboardingWidget, HttpServletResponse response) { + FnUser user = fnUserService.loadUserByUsername(principal.getName()); + FieldsValidator fieldsValidator = null; + if (onboardingWidget!=null){ + if(!dataValidator.isValid(onboardingWidget)){ + fieldsValidator = new FieldsValidator(); + fieldsValidator.setHttpStatusCode((long)HttpServletResponse.SC_NOT_ACCEPTABLE); + return fieldsValidator; + } + } + + if (userHasPermissions(user, response, "putOnboardingWidget")) { + assert onboardingWidget != null; + onboardingWidget.setId(widgetId); + onboardingWidget.normalize(); + fieldsValidator = widgetService.setOnboardingWidget(user, onboardingWidget); + response.setStatus(fieldsValidator.getHttpStatusCode().intValue()); + } + EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/widgets/" + widgetId, "GET result =", response.getStatus()); + + return fieldsValidator; + } + + private boolean userHasPermissions(FnUser user, HttpServletResponse response, String invocator) { + if (!adminRolesService.isSuperAdmin(user) && !adminRolesService.isAccountAdmin(user)) { + EcompPortalUtils.setBadPermissions(user, response, invocator); + return false; + } + return true; + } } diff --git a/portal-BE/src/main/java/org/onap/portal/dao/fn/FnWidgetDao.java b/portal-BE/src/main/java/org/onap/portal/dao/fn/FnWidgetDao.java new file mode 100644 index 00000000..a47a1a0d --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/dao/fn/FnWidgetDao.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.fn; + +import org.onap.portal.domain.db.fn.FnWidget; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional +public interface FnWidgetDao extends JpaRepository<FnWidget, Long> { + +} diff --git a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnWidget.java b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnWidget.java new file mode 100644 index 00000000..649267bf --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnWidget.java @@ -0,0 +1,71 @@ +/* + * ============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.domain.db.fn; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Table(name = "fn_widget") +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Entity +public class FnWidget { + @Id + private Long widgetId; + @Column(name = "WDG_NAME") + private String name; + @Column(name = "WDG_WIDTH") + private Integer width; + @Column(name = "WDG_HEIGHT") + private Integer height; + @Column(name = "WDG_URL") + private String url; + @Column(name = "APP_ID") + private Long appId; +} diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserApp.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserApp.java index 5eb0da96..52d42fb9 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserApp.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/EPUserApp.java @@ -60,8 +60,15 @@ public class EPUserApp extends DomainVo implements java.io.Serializable, Compara private EPApp app; @Valid private EPRole role; + private Integer priority; - + + public EPUserApp(final Long userId, final EPApp app, final EPRole role) { + this.userId = userId; + this.app = app; + this.role = role; + } + public Long getAppId() { return this.getApp().getId(); } diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/Widget.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/Widget.java index 86c92269..206484fa 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/Widget.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/ecomp/Widget.java @@ -66,6 +66,12 @@ public class Widget extends DomainVo { this.url = ""; } + public Widget(Long appId, String name, String url) { + this.name = name; + this.url = url; + this.appId = appId; + } + public void setName(String name) { if (StringUtils.isEmpty(name)) { name = ""; diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/FieldsValidator.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/FieldsValidator.java index d2bdd944..1999d236 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/FieldsValidator.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/FieldsValidator.java @@ -60,6 +60,10 @@ public class FieldsValidator { private Long errorCode; private List<FieldName> fields = new ArrayList<>(); + public void addProblematicFieldName(String fieldName){ + fields.add(new FieldName(fieldName)); + } + @Getter @Setter @ToString @@ -68,5 +72,4 @@ public class FieldsValidator { public class FieldName { public String name; } - } diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/OnboardingWidget.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/OnboardingWidget.java index e08d0339..de13bec5 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/OnboardingWidget.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/transport/OnboardingWidget.java @@ -41,7 +41,6 @@ package org.onap.portal.domain.dto.transport; import java.io.Serializable; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -50,30 +49,43 @@ import org.hibernate.validator.constraints.SafeHtml; @Getter @Setter @NoArgsConstructor -@AllArgsConstructor public class OnboardingWidget implements Serializable { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private Long id; - @SafeHtml - private String name; - private Long appId; - @SafeHtml - private String appName; - private Integer width; - private Integer height; - @SafeHtml - private String url; + private Long id; + @SafeHtml + private String name; + private Long appId; + @SafeHtml + private String appName; + private Integer width; + private Integer height; + @SafeHtml + private String url; - public void normalize() { - this.name = (this.name == null) ? "" : this.name.trim(); - this.appName = (this.appName == null) ? "" : this.appName.trim(); - if (this.width == null) - this.width = 0; - if (this.height == null) - this.height = 0; - this.url = (this.url == null) ? "" : this.url.trim(); - } + public OnboardingWidget(Long id, String name, Long appId, + String appName, Integer width, Integer height, + String url) { + this.id = id; + this.name = name; + this.appId = appId; + this.appName = appName; + this.width = width; + this.height = height; + this.url = url; + } + + public void normalize() { + this.name = (this.name == null) ? "" : this.name.trim(); + this.appName = (this.appName == null) ? "" : this.appName.trim(); + if (this.width == null) { + this.width = 0; + } + if (this.height == null) { + this.height = 0; + } + this.url = (this.url == null) ? "" : this.url.trim(); + } } diff --git a/portal-BE/src/main/java/org/onap/portal/service/WidgetService.java b/portal-BE/src/main/java/org/onap/portal/service/WidgetService.java index 24a77ed5..491ce4cc 100644 --- a/portal-BE/src/main/java/org/onap/portal/service/WidgetService.java +++ b/portal-BE/src/main/java/org/onap/portal/service/WidgetService.java @@ -43,60 +43,205 @@ package org.onap.portal.service; import java.util.ArrayList; import java.util.List; import javax.persistence.EntityManager; +import javax.servlet.http.HttpServletResponse; +import org.onap.portal.dao.fn.FnWidgetDao; import org.onap.portal.domain.db.fn.FnUser; +import org.onap.portal.domain.db.fn.FnWidget; +import org.onap.portal.domain.dto.ecomp.EPUserApp; +import org.onap.portal.domain.dto.ecomp.Widget; +import org.onap.portal.domain.dto.transport.FieldsValidator; import org.onap.portal.domain.dto.transport.OnboardingWidget; +import org.onap.portal.utils.EPCommonSystemProperties; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service public class WidgetService { - private final AdminRolesService adminRolesService; - - private static Long ACCOUNT_ADMIN_ROLE_ID = 999L; + private final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(WidgetService.class); + private final Long LONG_ECOMP_APP_ID = 1L; + private final Long ACCOUNT_ADMIN_ROLE_ID = 999L; - private static String baseSqlToken = " widget.WIDGET_ID, widget.WDG_NAME, widget.APP_ID, app.APP_NAME, widget.WDG_WIDTH, widget.WDG_HEIGHT, widget.WDG_URL" - + " from FN_WIDGET widget join FN_APP app ON widget.APP_ID = app.APP_ID"; + private static String baseSqlToken = + " new org.onap.portal.domain.dto.transport.OnboardingWidget(" + + "widget.WIDGET_ID,widget.WDG_NAME,widget.APP_ID," + + "app.APP_NAME,widget.WDG_WIDTH,widget.WDG_HEIGHT," + + "widget.WDG_URL) widget.WIDGET_ID,widget.WDG_NAME,widget.APP_ID,app.APP_NAME,widget.WDG_WIDTH,widget.WDG_HEIGHT,widget.WDG_URL from FN_WIDGET widget join FN_APP app ON widget.APP_ID = app.APP_ID"; - private static String validAppsFilter = ""; + private static final String urlField = "url"; + private static final Long DUBLICATED_FIELD_VALUE_ECOMP_ERROR = new Long( + EPCommonSystemProperties.DUBLICATED_FIELD_VALUE_ECOMP_ERROR); + private static final String nameField = "name"; + private final AdminRolesService adminRolesService; private final EntityManager entityManager; + private final FnWidgetDao fnWidgetDao; @Autowired - public WidgetService(final AdminRolesService adminRolesService, EntityManager entityManager) { + public WidgetService(final AdminRolesService adminRolesService, final EntityManager entityManager, + final FnWidgetDao fnWidgetDao) { this.adminRolesService = adminRolesService; this.entityManager = entityManager; + this.fnWidgetDao = fnWidgetDao; } + private static final Object syncRests = new Object(); + public List<OnboardingWidget> getOnboardingWidgets(FnUser user, boolean managed) { - List<OnboardingWidget> onboardingWidgets = new ArrayList<>(); - String sql = null; if (adminRolesService.isSuperAdmin(user)) { - sql = this.sqlWidgetsForAllApps(); + return entityManager.createQuery(sqlWidgetsForAllApps(), OnboardingWidget.class).getResultList(); } else if (managed) { if (adminRolesService.isAccountAdmin(user)) { - sql = this.sqlWidgetsForAllAppsWhereUserIsAdmin(user.getId()); + return entityManager + .createQuery(sqlWidgetsForAllAppsWhereUserIsAdmin(), OnboardingWidget.class) + .setParameter("USERID", user.getId()).getResultList(); } } else if (adminRolesService.isAccountAdmin(user) || adminRolesService.isUser(user)) { - sql = this.sqlWidgetsForAllAppsWhereUserHasAnyRole(user.getId()); - } - if (sql != null) { - onboardingWidgets = (List<OnboardingWidget>) entityManager.createNativeQuery(sql, OnboardingWidget.class).getResultList(); + return entityManager + .createQuery(sqlWidgetsForAllAppsWhereUserHasAnyRole(), OnboardingWidget.class) + .setParameter("USERID", user.getId()).getResultList(); } - return onboardingWidgets; + return new ArrayList<>(); } private String sqlWidgetsForAllApps() { - return "SELECT" + baseSqlToken + validAppsFilter; + return "SELECT" + baseSqlToken; + } + + private String sqlWidgetsForAllAppsWhereUserIsAdmin() { + return "SELECT" + baseSqlToken + + " join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = app.APP_ID where FN_USER_ROLE.USER_ID = :USERID AND FN_USER_ROLE.ROLE_ID = " + + ACCOUNT_ADMIN_ROLE_ID; + } + + private String sqlWidgetsForAllAppsWhereUserHasAnyRole() { + return "SELECT DISTINCT" + baseSqlToken + + " join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = app.APP_ID where FN_USER_ROLE.USER_ID = " + + ":USERID"; } - private String sqlWidgetsForAllAppsWhereUserHasAnyRole(Long userId) { - return "SELECT DISTINCT" + baseSqlToken + " join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = app.APP_ID where FN_USER_ROLE.USER_ID = " - + userId + validAppsFilter; + public FieldsValidator setOnboardingWidget(FnUser user, OnboardingWidget onboardingWidget) { + if (onboardingWidget.getAppName().isEmpty() || onboardingWidget.getUrl().isEmpty() + || onboardingWidget.getAppId() == null + || onboardingWidget.getAppId().equals(LONG_ECOMP_APP_ID) || onboardingWidget.getWidth() <= 0 || + onboardingWidget.getHeight() <= 0) { + FieldsValidator fieldsValidator = new FieldsValidator(); + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_BAD_REQUEST); + return fieldsValidator; + } + return this.updateOrSaveWidget(adminRolesService.isSuperAdmin(user), user.getId(), onboardingWidget); } - private String sqlWidgetsForAllAppsWhereUserIsAdmin(Long userId) { - return "SELECT" + baseSqlToken + " join FN_USER_ROLE ON FN_USER_ROLE.APP_ID = app.APP_ID where FN_USER_ROLE.USER_ID = " + userId - + " AND FN_USER_ROLE.ROLE_ID = " + ACCOUNT_ADMIN_ROLE_ID + validAppsFilter; + private FieldsValidator updateOrSaveWidget(boolean superAdmin, Long userId, OnboardingWidget onboardingWidget) { + FieldsValidator fieldsValidator = new FieldsValidator(); + if (!this.isUserAdminOfAppForWidget(superAdmin, userId, onboardingWidget.getAppId())) { + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_FORBIDDEN); + return fieldsValidator; + } + synchronized (syncRests) { + if (onboardingWidget.getId() == null) { + this.validateOnboardingWidget(onboardingWidget, fieldsValidator); + } else { + FnWidget widget = fnWidgetDao.getOne(onboardingWidget.getId()); + if (widget == null || widget.getAppId() == null) { + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_NOT_FOUND); + return fieldsValidator; + } + this.validateOnboardingWidget(onboardingWidget, fieldsValidator); + } + if (fieldsValidator.getHttpStatusCode() == HttpServletResponse.SC_OK) { + this.applyOnboardingWidget(onboardingWidget, fieldsValidator); + } + } + return fieldsValidator; } + + private boolean isUserAdminOfAppForWidget(boolean superAdmin, Long userId, Long appId) { + if (!superAdmin) { + List<EPUserApp> userRoles = getAdminUserRoles(userId, appId); + return (userRoles.size() > 0); + } + return true; + } + + private List<EPUserApp> getAdminUserRoles(Long userId, Long appId) { + return entityManager.createQuery( + "SELECT new org.onap.portal.domain.dto.ecomp.EPUserApp(fn.userId, fn.roleId, fn.appId) FROM FnUserRole fn" + + "WHERE fn.userId = :USERID " + + "AND fn.roleId = :ROLEID " + + "AND fn.appId = :APPID", EPUserApp.class) + .setParameter("USERID", userId) + .setParameter("ROLEID", ACCOUNT_ADMIN_ROLE_ID) + .setParameter("APPID", appId) + .getResultList(); + } + + @Transactional + private void applyOnboardingWidget(OnboardingWidget onboardingWidget, FieldsValidator fieldsValidator) { + boolean result; + FnWidget widget; + if (onboardingWidget.getId() == null) { + widget = new FnWidget(); + } else { + widget = fnWidgetDao.getOne(onboardingWidget.getId()); + } + widget.setAppId(onboardingWidget.getAppId()); + widget.setName(onboardingWidget.getName()); + widget.setWidth(onboardingWidget.getWidth()); + widget.setHeight(onboardingWidget.getHeight()); + widget.setUrl(onboardingWidget.getUrl()); + result = widget.equals(fnWidgetDao.saveAndFlush(widget)); + if (!result) { + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + private void validateOnboardingWidget(OnboardingWidget onboardingWidget, FieldsValidator fieldsValidator) { + List<Widget> widgets = getWidgets(onboardingWidget); + boolean dublicatedUrl = false; + boolean dublicatedName = false; + for (Widget widget : widgets) { + if (onboardingWidget.getId() != null && onboardingWidget.getId().equals(widget.getId())) { + // widget should not be compared with itself + continue; + } + if (!dublicatedUrl && widget.getUrl().equals(onboardingWidget.getUrl())) { + dublicatedUrl = true; + if (dublicatedName) { + break; + } + } + if (!dublicatedName && widget.getName().equalsIgnoreCase(onboardingWidget.getName()) && widget + .getAppId().equals(onboardingWidget.getAppId())) { + dublicatedName = true; + if (dublicatedUrl) { + break; + } + } + } + if (dublicatedUrl || dublicatedName) { + if (dublicatedUrl) { + fieldsValidator.addProblematicFieldName(urlField); + } + if (dublicatedName) { + fieldsValidator.addProblematicFieldName(nameField); + } + fieldsValidator.setHttpStatusCode((long) HttpServletResponse.SC_CONFLICT); + fieldsValidator.setErrorCode(DUBLICATED_FIELD_VALUE_ECOMP_ERROR); + } + } + + private List<Widget> getWidgets(OnboardingWidget onboardingWidget) { + return entityManager.createQuery( + "SELECT new org.onap.portal.domain.dto.ecomp.Widget(fn.APP_ID, fn.WDG_NAME, fn.WDG_URL) FROM FnWidget fn" + + "WHERE fn.WDG_URL = :WDGURL " + + "AND fn.WDG_NAME = :WDGNAME " + + "AND fn.APP_ID = :APPID", Widget.class) + .setParameter("WDGURL", onboardingWidget.getUrl()) + .setParameter("WDGNAME", onboardingWidget.getName()) + .getResultList(); + } + } |