diff options
author | Manoop Talasila <talasila@research.att.com> | 2019-08-28 18:52:01 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2019-08-28 18:52:01 +0000 |
commit | 19155f5cde7703be3449050b57d90554836271af (patch) | |
tree | 326a5e8348097bd461aa6146711ecdd48b730fdb | |
parent | d65ad49ae821bb2e3bf1c75886c13df004e00613 (diff) | |
parent | 233bc890b4c79e78ff7c654568ff5b327df7648f (diff) |
Merge "Portal Spring Boot Development"
8 files changed, 424 insertions, 5 deletions
diff --git a/portal-BE/pom.xml b/portal-BE/pom.xml index 6a42e871..a7e8588f 100644 --- a/portal-BE/pom.xml +++ b/portal-BE/pom.xml @@ -50,6 +50,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs <optional>true</optional> </dependency> <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-aop</artifactId> + <version>2.1.6.RELEASE</version> + </dependency> + <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> @@ -59,6 +64,24 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> + <!-- https://mvnrepository.com/artifact/org.glassfish/javax.el --> + <dependency> + <groupId>org.glassfish</groupId> + <artifactId>javax.el</artifactId> + <version>3.0.1-b11</version> + </dependency> + <!-- https://mvnrepository.com/artifact/javax.el/el-api --> + <dependency> + <groupId>javax.el</groupId> + <artifactId>el-api</artifactId> + <version>2.2.1-b04</version> + </dependency> + <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> + <dependency> + <groupId>org.jsoup</groupId> + <artifactId>jsoup</artifactId> + <version>1.12.1</version> + </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> diff --git a/portal-BE/src/main/java/org/onap/portal/aop/service/FnLanguageServiceAOP.java b/portal-BE/src/main/java/org/onap/portal/aop/service/FnLanguageServiceAOP.java new file mode 100644 index 00000000..250a6e2d --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/aop/service/FnLanguageServiceAOP.java @@ -0,0 +1,77 @@ +/* + * ============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.aop.service; + +import java.security.Principal; +import java.util.stream.Collectors; +import javax.validation.ConstraintViolation; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.onap.portal.domain.db.fn.FnLanguage; +import org.onap.portal.validation.DataValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class FnLanguageServiceAOP { + private static final Logger LOGGER = LoggerFactory.getLogger(FnLanguageServiceAOP.class); + + @Autowired + private DataValidator dataValidator; + + @Before("execution(* org.onap.portal.service.fn.FnLanguageService.save(..)) && args(principal, fnLanguage)") + public void save(final Principal principal, final FnLanguage fnLanguage) { + if (fnLanguage == null) { + LOGGER.error("User " + principal.getName() + " try to save NULL fnLanguage"); + throw new NullPointerException("FnLanguage cannot be null or empty"); + } + if (!dataValidator.isValid(fnLanguage)) { + String violations = dataValidator.getConstraintViolations(fnLanguage).stream() + .map(ConstraintViolation::getMessage) + .collect(Collectors.joining(", ")); + LOGGER.error("User " + principal.getName() + " try to save not valid fnLanguage: " + violations); + throw new IllegalArgumentException("FnLanguage is not valid, " + violations); + } + } +} diff --git a/portal-BE/src/main/java/org/onap/portal/controller/LanguageController.java b/portal-BE/src/main/java/org/onap/portal/controller/LanguageController.java index 2c88694c..2ea4ff24 100644 --- a/portal-BE/src/main/java/org/onap/portal/controller/LanguageController.java +++ b/portal-BE/src/main/java/org/onap/portal/controller/LanguageController.java @@ -40,15 +40,23 @@ package org.onap.portal.controller; +import java.security.Principal; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.onap.portal.aop.service.FnLanguageServiceAOP; import org.onap.portal.domain.db.fn.FnLanguage; import org.onap.portal.domain.db.fn.FnUser; +import org.onap.portal.domain.dto.PortalRestResponse; +import org.onap.portal.domain.dto.PortalRestStatusEnum; import org.onap.portal.service.fn.FnLanguageService; import org.onap.portal.service.fn.FnUserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -57,6 +65,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/auxapi") public class LanguageController { + private static final Logger LOGGER = LoggerFactory.getLogger(LanguageController.class); private final FnLanguageService languageService; private final FnUserService fnUserService; @@ -68,12 +77,12 @@ public class LanguageController { this.fnUserService = fnUserService; } - @RequestMapping(value = "/language",method = RequestMethod.GET, produces = "application/json;charset=UTF-8") + @GetMapping(value = "/language", produces = "application/json;charset=UTF-8") public List<FnLanguage> getLanguageList() { return languageService.getLanguages(); } - @RequestMapping(value = "/languageSetting/user/{loginId}",method = RequestMethod.POST) + @PostMapping(value = "/languageSetting/user/{loginId}") public void setUpUserLanguage(@RequestBody FnLanguage fnLanguage, @PathVariable("loginId") Long loginId) { if (fnUserService.getUser(loginId).isPresent()){ @@ -83,7 +92,7 @@ public class LanguageController { } } - @RequestMapping(value = "/languageSetting/user/{loginId}",method = RequestMethod.GET) + @GetMapping(value = "/languageSetting/user/{loginId}") public FnLanguage getUserLanguage(HttpServletRequest request, HttpServletResponse response, @PathVariable("loginId") Long loginId) { if (fnUserService.getUser(loginId).isPresent()){ @@ -93,4 +102,20 @@ public class LanguageController { return new FnLanguage(); } + @PostMapping(value = "/language") + public PortalRestResponse<String> saveLanguage(final Principal principal, final FnLanguage fnLanguage){ + PortalRestResponse<String> response = new PortalRestResponse<>(); + try { + response.setMessage("SUCCESS"); + response.setResponse(languageService.save(principal, fnLanguage).toString()); + response.setStatus(PortalRestStatusEnum.OK); + } catch (Exception e){ + response.setMessage("FAILURE"); + response.setResponse(e.getMessage()); + response.setStatus(PortalRestStatusEnum.ERROR); + return response; + } + return response; + } + } diff --git a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnLanguage.java b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnLanguage.java index f8dfac28..09cb5a6e 100644 --- a/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnLanguage.java +++ b/portal-BE/src/main/java/org/onap/portal/domain/db/fn/FnLanguage.java @@ -45,6 +45,7 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.validation.constraints.Digits; import javax.validation.constraints.NotNull; @@ -53,6 +54,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; import org.hibernate.validator.constraints.SafeHtml; /* CREATE TABLE `fn_language` ( @@ -66,13 +68,15 @@ CREATE TABLE `fn_language` ( @Table(name = "fn_language") @NoArgsConstructor @AllArgsConstructor +@ToString @Getter @Setter @Entity +@SequenceGenerator(name="seq", initialValue=3, allocationSize=100) public class FnLanguage { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") @Column(name = "language_id", length = 11, nullable = false, columnDefinition = "int(11) AUTO_INCREMENT") @Digits(integer = 11, fraction = 0) private Long languageId; diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/PortalRestResponse.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/PortalRestResponse.java new file mode 100644 index 00000000..f1ca07f5 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/PortalRestResponse.java @@ -0,0 +1,122 @@ +/* + * ============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.dto; + +public class PortalRestResponse<T> { + + private PortalRestStatusEnum status; + private String message; + + private T response; + + public PortalRestResponse(){}; + + public PortalRestResponse(PortalRestStatusEnum status, String message, T response){ + this.status = status; + this.message = message; + this.response = response; + } + + public PortalRestStatusEnum getStatus() { + return status; + } + + public void setStatus(PortalRestStatusEnum status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getResponse() { + return response; + } + + public void setResponse(T response) { + this.response = response; + } + + @Override + public String toString() { + return "PortalRestResponse [status=" + status + ", message=" + message + ", response=" + response + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((message == null) ? 0 : message.hashCode()); + result = prime * result + ((response == null) ? 0 : response.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PortalRestResponse other = (PortalRestResponse) obj; + if (message == null) { + if (other.message != null) + return false; + } else if (!message.equals(other.message)) + return false; + if (response == null) { + if (other.response != null) + return false; + } else if (!response.equals(other.response)) + return false; + if (status != other.status) + return false; + return true; + }; + + +} diff --git a/portal-BE/src/main/java/org/onap/portal/domain/dto/PortalRestStatusEnum.java b/portal-BE/src/main/java/org/onap/portal/domain/dto/PortalRestStatusEnum.java new file mode 100644 index 00000000..0a175f65 --- /dev/null +++ b/portal-BE/src/main/java/org/onap/portal/domain/dto/PortalRestStatusEnum.java @@ -0,0 +1,57 @@ +/* + * ============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.dto; + +public enum PortalRestStatusEnum{ + OK("ok"), + WARN("WARNING"), + ERROR("error"); + + private String value; + private PortalRestStatusEnum(String value){ + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/portal-BE/src/main/java/org/onap/portal/service/fn/FnLanguageService.java b/portal-BE/src/main/java/org/onap/portal/service/fn/FnLanguageService.java index cdbba06a..da9c0482 100644 --- a/portal-BE/src/main/java/org/onap/portal/service/fn/FnLanguageService.java +++ b/portal-BE/src/main/java/org/onap/portal/service/fn/FnLanguageService.java @@ -40,6 +40,7 @@ package org.onap.portal.service.fn; +import java.security.Principal; import java.util.List; import java.util.Optional; import org.onap.portal.dao.fn.FnLanguageDao; @@ -56,10 +57,13 @@ public class FnLanguageService { this.fnLanguageDao = fnLanguageDao; } - public Optional<FnLanguage> findById(Long id){ + public Optional<FnLanguage> findById(final Long id){ return fnLanguageDao.findById(id); } public List<FnLanguage> getLanguages(){ return fnLanguageDao.findAll(); } + public FnLanguage save(final Principal principal, final FnLanguage fnLanguage){ + return fnLanguageDao.save(fnLanguage); + } } diff --git a/portal-BE/src/test/java/org/onap/portal/controller/LanguageControllerTest.java b/portal-BE/src/test/java/org/onap/portal/controller/LanguageControllerTest.java new file mode 100644 index 00000000..0015c00b --- /dev/null +++ b/portal-BE/src/test/java/org/onap/portal/controller/LanguageControllerTest.java @@ -0,0 +1,107 @@ +/* + * ============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.controller; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.onap.portal.dao.fn.FnLanguageDao; +import org.onap.portal.domain.db.fn.FnLanguage; +import org.onap.portal.domain.dto.PortalRestResponse; +import org.onap.portal.domain.dto.PortalRestStatusEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +@TestPropertySource(locations="classpath:test.properties") +class LanguageControllerTest { + private UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken("demo", "XZa6pS1vC0qKXWtn9wcZWdLx61L0="); + + @Autowired + private LanguageController languageController; + @Autowired + private FnLanguageDao fnLanguageDao; + + @Test + void saveLanguage() { + //Given + FnLanguage fnLanguage = new FnLanguage(); + fnLanguage.setLanguageName("Polish"); + fnLanguage.setLanguageAlias("PL"); + //When + PortalRestResponse<String> expected = new PortalRestResponse<>(); + expected.setMessage("SUCCESS"); + expected.setResponse("FnLanguage(languageId=3, languageName=Polish, languageAlias=PL)"); + expected.setStatus(PortalRestStatusEnum.OK); + PortalRestResponse<String> actual = languageController.saveLanguage(principal, fnLanguage); + //Then + + assertEquals(expected, actual); + //Clean up + fnLanguageDao.delete(fnLanguage); + } + + @Test + void saveLanguageXSS() { + //Given + FnLanguage fnLanguage = new FnLanguage(); + fnLanguage.setLanguageName("<script>alert(“XSS”)</script> "); + fnLanguage.setLanguageAlias("PL"); + //When + PortalRestResponse<String> expected = new PortalRestResponse<>(); + expected.setMessage("FAILURE"); + expected.setResponse("FnLanguage is not valid, may have unsafe html content"); + expected.setStatus(PortalRestStatusEnum.ERROR); + PortalRestResponse<String> actual = languageController.saveLanguage(principal, fnLanguage); + //Then + + assertEquals(expected, actual); + //Clean up + fnLanguageDao.delete(fnLanguage); + } + +}
\ No newline at end of file |