diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..11aca202 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "migrations"] + path = migrations + url = https://github.com/reportportal/migrations diff --git a/build.gradle b/build.gradle index 0413845a..f02c75cc 100644 --- a/build.gradle +++ b/build.gradle @@ -32,21 +32,7 @@ ext['hibernate-validator.version'] = '6.1.5.Final' ext['log4j2.version'] = '2.21.1' -dependencyManagement { - imports { - mavenBom(releaseMode ? 'com.epam.reportportal:commons-bom:' + '5.13.0' : 'com.epam.reportportal:commons-bom:5.13.0') - } -} - dependencies { - if (releaseMode) { - api 'com.epam.reportportal:commons-dao' - api 'com.epam.reportportal:commons' - } else { - api 'com.github.reportportal:commons-dao:develop-SNAPSHOT' - api 'com.github.reportportal:commons:develop-SNAPSHOT' - } - //Fix CVE-2021-41079, CVE-2022-23181, CVE-2021-33037, CVE-2021-30640, CVE-2022-42252, CVE-2023-46589, CVE-2024-24549 implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.86' implementation 'org.apache.tomcat.embed:tomcat-embed-el:9.0.86' @@ -59,7 +45,11 @@ dependencies { api 'org.apache.httpcomponents:httpclient:4.5.14' //Fix CVE-2022-40152 api 'com.fasterxml.woodstox:woodstox-core:6.5.1' - + implementation('org.springframework.boot:spring-boot-starter-data-jpa') { + exclude group: 'org.hibernate', module: 'hibernate-core' + } + implementation 'org.postgresql:postgresql:42.7.3' + api 'org.jasypt:jasypt:1.9.3' api 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' api 'org.springframework.boot:spring-boot-starter-security' @@ -69,13 +59,23 @@ dependencies { //Fix CVE-2023-40827, CVE-2023-40828, CVE-2023-40826 implementation 'org.springframework:spring-webmvc:5.3.39' implementation 'org.springframework:spring-web:5.3.39' + implementation "org.apache.commons:commons-lang3:${commonsLangVersion}" + implementation 'net.coobird:thumbnailator:0.4.20' + implementation("org.apache.tika:tika-core:3.0.0") + + api "org.apache.jclouds.api:s3:${jclouds}" // 2.6.0 switched to jakarta annotations! + implementation "org.apache.jclouds.provider:aws-s3:${jclouds}" + implementation "org.apache.jclouds.api:filesystem:${jclouds}" + api('commons-validator:commons-validator:1.6') { + exclude group: 'commons-beanutils', module: 'commons-beanutils' + } ///// Security //https://nvd.nist.gov/vuln/detail/CVE-2020-5407 AND https://nvd.nist.gov/vuln/detail/CVE-2020-5408 implementation 'org.springframework.security:spring-security-core:5.8.16' implementation 'org.springframework.security:spring-security-config:5.8.16' implementation 'org.springframework.security:spring-security-web:5.8.16' - implementation 'org.springframework:spring-jdbc:6.1.5' + implementation 'org.springframework:spring-jdbc:5.3.33' // api 'org.springframework.security:spring-security-oauth2-client' @@ -108,7 +108,7 @@ dependencies { // TODO: snakeyaml 2.0 supported by Spring Boot 2.7 and 3.X only // We don't user application.yml, so it's safe to use 2.2 implementation 'org.yaml:snakeyaml:2.2' - implementation 'org.hibernate:hibernate-core:5.4.24.Final' + implementation 'org.hibernate:hibernate-core:5.6.15.Final' implementation 'org.springframework:spring-core:5.3.39' implementation "com.rabbitmq:http-client:5.2.0" @@ -117,6 +117,22 @@ dependencies { annotationProcessor "org.projectlombok:lombok:${lombokVersion}" testCompileOnly "org.projectlombok:lombok:${lombokVersion}" testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}" + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.flywaydb.flyway-test-extensions:flyway-spring-test:6.1.0' + + // testImplementation 'org.springframework.boot:spring-boot-testcontainers:' // spring boot 3.1+ + // compileOnly("org.springframework.boot:spring-boot-devtools") + implementation platform("org.testcontainers:testcontainers-bom:${testContainers}") + testImplementation "org.testcontainers:junit-jupiter:${testContainers}" + testImplementation "org.testcontainers:postgresql:${testContainers}" + testImplementation("org.testcontainers:minio:${testContainers}") + +} + + +tasks.register('updateSubmodule', Exec) { + commandLine 'git', 'submodule', 'update', '--init' } processResources { @@ -141,10 +157,19 @@ bootJar { jar.enabled(true) jar.archiveClassifier.set('') +test { + jvmArgs '--add-opens=java.base/java.lang=ALL-UNNAMED' // TODO: remove in Spring Boot 3 + useJUnitPlatform() + testLogging { + events = ["failed"] + exceptionFormat = "short" + } +} +compileJava.dependsOn updateSubmodule publish.dependsOn build publish.mustRunAfter build tasks.preTagCommit.enabled = false tasks.updateVersion.enabled = false -tasks.commitNewVersion.enabled = false \ No newline at end of file +tasks.commitNewVersion.enabled = false diff --git a/gradle.properties b/gradle.properties index a861a038..6213f74c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,3 +6,6 @@ dockerJavaOptsDev=-Xmx1g -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=70 -XX: dockerServerUrl=unix:///var/run/docker.sock lombokVersion=1.18.30 +commonsLangVersion=3.9 +testContainers=1.20.4 +jclouds=2.5.0 diff --git a/migrations b/migrations new file mode 160000 index 00000000..ef2fb9f1 --- /dev/null +++ b/migrations @@ -0,0 +1 @@ +Subproject commit ef2fb9f141400e00b680a8721c72e86f1e2b9bdf diff --git a/src/main/java/com/epam/reportportal/auth/AdminPasswordInitializer.java b/src/main/java/com/epam/reportportal/auth/AdminPasswordInitializer.java index 8efe4ef3..8ffab943 100644 --- a/src/main/java/com/epam/reportportal/auth/AdminPasswordInitializer.java +++ b/src/main/java/com/epam/reportportal/auth/AdminPasswordInitializer.java @@ -18,9 +18,9 @@ import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.user.User; import com.epam.reportportal.auth.exception.EnvironmentVariablesNotProvidedException; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.user.User; import java.util.Optional; import javax.persistence.EntityNotFoundException; import org.apache.commons.lang3.StringUtils; diff --git a/src/main/java/com/epam/reportportal/auth/AuthConfigService.java b/src/main/java/com/epam/reportportal/auth/AuthConfigService.java index f8053f41..edfc004e 100644 --- a/src/main/java/com/epam/reportportal/auth/AuthConfigService.java +++ b/src/main/java/com/epam/reportportal/auth/AuthConfigService.java @@ -19,10 +19,10 @@ import static com.google.common.reflect.Reflection.newProxy; import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; import com.epam.reportportal.auth.integration.converter.OAuthRegistrationConverters; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import com.epam.reportportal.auth.store.MutableClientRegistrationRepository; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; @@ -109,18 +109,18 @@ public OAuth2ProtectedResourceDetails loadResourceDetails(String name) { */ private static final Function RESOURCE_DETAILS_CONVERTER = d -> { - BaseOAuth2ProtectedResourceDetails details = getOauth2ProtectedResourceDetails(d); - details.setId(d.getId()); - details.setAccessTokenUri(d.getTokenUri()); - Arrays.stream(AuthenticationScheme.values()) - .filter(scheme -> scheme.name().equalsIgnoreCase(d.getClientAuthMethod())) - .findFirst() - .ifPresent(details::setClientAuthenticationScheme); - details.setClientId(d.getClientId()); - details.setClientSecret(d.getClientSecret()); - details.setScope(new ArrayList<>(d.getScopes())); - return details; - }; + BaseOAuth2ProtectedResourceDetails details = getOauth2ProtectedResourceDetails(d); + details.setId(d.getId()); + details.setAccessTokenUri(d.getTokenUri()); + Arrays.stream(AuthenticationScheme.values()) + .filter(scheme -> scheme.name().equalsIgnoreCase(d.getClientAuthMethod())) + .findFirst() + .ifPresent(details::setClientAuthenticationScheme); + details.setClientId(d.getClientId()); + details.setClientSecret(d.getClientSecret()); + details.setScope(new ArrayList<>(d.getScopes())); + return details; + }; private static BaseOAuth2ProtectedResourceDetails getOauth2ProtectedResourceDetails( OAuthRegistrationResource oAuthRegistrationResource) { diff --git a/src/main/java/com/epam/reportportal/auth/AuthServerApplication.java b/src/main/java/com/epam/reportportal/auth/AuthServerApplication.java index 9a3fd03a..926f9a21 100644 --- a/src/main/java/com/epam/reportportal/auth/AuthServerApplication.java +++ b/src/main/java/com/epam/reportportal/auth/AuthServerApplication.java @@ -23,19 +23,16 @@ import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; -import org.springframework.context.annotation.ComponentScan; /** * Application entry point. * * @author Andrei Varabyeu */ -//@Import({ DatabaseConfiguration.class, DatastoreConfiguration.class }) @SpringBootApplication(exclude = {LdapHealthContributorAutoConfiguration.class, FlywayAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class, ReactiveElasticsearchRepositoriesAutoConfiguration.class}) -@ComponentScan(basePackages = {"com.epam.ta.reportportal", "com.epam.reportportal.auth"}) public class AuthServerApplication { public static void main(String[] args) { diff --git a/src/main/java/com/epam/reportportal/auth/EnableableAuthProvider.java b/src/main/java/com/epam/reportportal/auth/EnableableAuthProvider.java index 4a5bc746..9cf9bb8b 100644 --- a/src/main/java/com/epam/reportportal/auth/EnableableAuthProvider.java +++ b/src/main/java/com/epam/reportportal/auth/EnableableAuthProvider.java @@ -16,8 +16,8 @@ package com.epam.reportportal.auth; +import com.epam.reportportal.auth.dao.IntegrationRepository; import com.epam.reportportal.auth.event.UiUserSignedInEvent; -import com.epam.ta.reportportal.dao.IntegrationRepository; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; diff --git a/src/main/java/com/epam/reportportal/auth/OAuthSuccessHandler.java b/src/main/java/com/epam/reportportal/auth/OAuthSuccessHandler.java index 8ddf6336..cb2e8327 100644 --- a/src/main/java/com/epam/reportportal/auth/OAuthSuccessHandler.java +++ b/src/main/java/com/epam/reportportal/auth/OAuthSuccessHandler.java @@ -16,11 +16,11 @@ package com.epam.reportportal.auth; -import static com.epam.ta.reportportal.commons.EntityUtils.normalizeId; +import static com.epam.reportportal.auth.commons.EntityUtils.normalizeId; import static java.util.Optional.ofNullable; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.util.Collections; import javax.inject.Provider; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/epam/reportportal/auth/basic/BasicPasswordAuthenticationProvider.java b/src/main/java/com/epam/reportportal/auth/basic/BasicPasswordAuthenticationProvider.java index 8da0a998..85349d6d 100644 --- a/src/main/java/com/epam/reportportal/auth/basic/BasicPasswordAuthenticationProvider.java +++ b/src/main/java/com/epam/reportportal/auth/basic/BasicPasswordAuthenticationProvider.java @@ -18,8 +18,8 @@ import com.epam.reportportal.auth.event.UiAuthenticationFailureEventHandler; import com.epam.reportportal.auth.event.UiUserSignedInEvent; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import javax.inject.Provider; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/epam/reportportal/auth/basic/DatabaseUserDetailsService.java b/src/main/java/com/epam/reportportal/auth/basic/DatabaseUserDetailsService.java index 40706591..baf0060a 100644 --- a/src/main/java/com/epam/reportportal/auth/basic/DatabaseUserDetailsService.java +++ b/src/main/java/com/epam/reportportal/auth/basic/DatabaseUserDetailsService.java @@ -16,16 +16,17 @@ package com.epam.reportportal.auth.basic; -import static com.epam.ta.reportportal.commons.EntityUtils.normalizeId; +import static com.epam.reportportal.auth.commons.EntityUtils.normalizeId; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.user.User; import com.epam.reportportal.auth.util.AuthUtils; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.user.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** @@ -34,6 +35,8 @@ * * @author Andrei Varabyeu */ + +@Service public class DatabaseUserDetailsService implements UserDetailsService { private UserRepository userRepository; @@ -46,7 +49,8 @@ public void setUserRepository(UserRepository userRepository) { @Override @Transactional(readOnly = true) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - ReportPortalUser user = userRepository.findUserDetails(normalizeId(username)) + ReportPortalUser user = userRepository.findByLogin(normalizeId(username)) + .map(rpUser -> ReportPortalUser.userBuilder().fromUser(rpUser)) .orElseThrow(() -> new UsernameNotFoundException("User not found")); UserDetails userDetails = org.springframework.security.core.userdetails.User.builder() diff --git a/src/main/java/com/epam/reportportal/auth/binary/DataStoreService.java b/src/main/java/com/epam/reportportal/auth/binary/DataStoreService.java new file mode 100644 index 00000000..3e6db513 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/DataStoreService.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary; + +import java.io.InputStream; +import java.util.List; +import java.util.Optional; + +/** + * @author Ihar Kahadouski + */ +public interface DataStoreService { + + String save(String fileName, InputStream data); + + String saveThumbnail(String fileName, InputStream data); + + void delete(String fileId); + + void deleteAll(List fileIds, String bucketName); + + void deleteContainer(String containerName); + + Optional load(String fileId); +} diff --git a/src/main/java/com/epam/reportportal/auth/binary/UserBinaryDataService.java b/src/main/java/com/epam/reportportal/auth/binary/UserBinaryDataService.java new file mode 100644 index 00000000..62cfb94e --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/UserBinaryDataService.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary; + +import com.epam.reportportal.auth.entity.attachment.BinaryData; +import com.epam.reportportal.auth.entity.user.User; +import java.io.InputStream; + +/** + * @author Ihar Kahadouski + */ +public interface UserBinaryDataService { + + void saveUserPhoto(User user, BinaryData binaryData); + + void saveUserPhoto(User user, InputStream inputStream, String contentType); + +} diff --git a/src/main/java/com/epam/reportportal/auth/binary/impl/AttachmentDataStoreService.java b/src/main/java/com/epam/reportportal/auth/binary/impl/AttachmentDataStoreService.java new file mode 100644 index 00000000..51842600 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/impl/AttachmentDataStoreService.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary.impl; + +import com.epam.reportportal.auth.commons.Thumbnailator; +import com.epam.reportportal.auth.filesystem.DataEncoder; +import com.epam.reportportal.auth.filesystem.DataStore; +import java.io.IOException; +import java.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +/** + * @author Ihar Kahadouski + */ +@Service("attachmentDataStoreService") +public class AttachmentDataStoreService extends CommonDataStoreService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AttachmentDataStoreService.class); + + private final Thumbnailator thumbnailator; + + @Autowired + public AttachmentDataStoreService(DataStore dataStore, DataEncoder dataEncoder, + @Qualifier("attachmentThumbnailator") Thumbnailator thumbnailator) { + super(dataStore, dataEncoder); + this.thumbnailator = thumbnailator; + } + + @Override + public String saveThumbnail(String fileName, InputStream data) { + try { + return dataEncoder.encode(dataStore.save(fileName, thumbnailator.createThumbnail(data))); + } catch (IOException e) { + LOGGER.error("Thumbnail is not created for file [{}]. Error:\n", fileName, e); + } + return null; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/binary/impl/CommonDataStoreService.java b/src/main/java/com/epam/reportportal/auth/binary/impl/CommonDataStoreService.java new file mode 100644 index 00000000..c76edbaa --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/impl/CommonDataStoreService.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary.impl; + +import static java.util.Optional.ofNullable; + +import com.epam.reportportal.auth.binary.DataStoreService; +import com.epam.reportportal.auth.filesystem.DataEncoder; +import com.epam.reportportal.auth.filesystem.DataStore; +import java.io.InputStream; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author Ihar Kahadouski + */ +public abstract class CommonDataStoreService implements DataStoreService { + + protected DataStore dataStore; + + protected DataEncoder dataEncoder; + + CommonDataStoreService(DataStore dataStore, DataEncoder dataEncoder) { + this.dataStore = dataStore; + this.dataEncoder = dataEncoder; + } + + @Override + public String save(String fileName, InputStream data) { + return dataEncoder.encode(dataStore.save(fileName, data)); + } + + @Override + public abstract String saveThumbnail(String fileName, InputStream data); + + @Override + public void delete(String fileId) { + dataStore.delete(dataEncoder.decode(fileId)); + } + + @Override + public void deleteAll(List fileIds, String bucketName) { + dataStore.deleteAll( + fileIds.stream().map(dataEncoder::decode).collect(Collectors.toList()), bucketName); + } + + @Override + public void deleteContainer(String containerName) { + dataStore.deleteContainer(containerName); + } + + @Override + public Optional load(String fileId) { + return ofNullable(dataStore.load(dataEncoder.decode(fileId))); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/binary/impl/DataStoreUtils.java b/src/main/java/com/epam/reportportal/auth/binary/impl/DataStoreUtils.java new file mode 100644 index 00000000..dfdbbc81 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/impl/DataStoreUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary.impl; + +import com.google.common.base.Strings; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import org.apache.commons.io.FilenameUtils; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.mime.MimeTypes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author Ihar Kahadouski + */ +public class DataStoreUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(DataStoreUtils.class); + + private static final String THUMBNAIL_PREFIX = "thumbnail-"; + + private static final String DOT = "."; + + static final String ROOT_USER_PHOTO_DIR = "users"; + + static final String ATTACHMENT_CONTENT_TYPE = "attachmentContentType"; + + static final String PROJECT_PATH = "project-data"; + + static final String USER_DATA_PATH = "user-data"; + + static final String PHOTOS_PATH = "photos"; + + public static final String INTEGRATION_SECRETS_PATH = "integration-secrets"; + + private DataStoreUtils() { + //static only + } + + /** + * Returns {@link Optional} of extension by contentType. + * + * @param contentType Content type + * @return {@link Optional} of {@link String} + */ + public static Optional resolveExtension(String contentType) { + Optional result = Optional.empty(); + try { + result = Optional.of(MimeTypes.getDefaultMimeTypes().forName(contentType).getExtension()); + } catch (MimeTypeException e) { + LOGGER.warn("Cannot resolve file extension from content type '{}'", contentType, e); + } + return result; + } + + public static String resolveExtension(boolean prefixDot, MultipartFile file) { + final String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + return prefixDot ? DOT + extension : extension; + } + + public static String buildThumbnailFileName(String commonPath, String fileName) { + Path thumbnailTargetPath = Paths.get(commonPath, THUMBNAIL_PREFIX.concat(fileName)); + return thumbnailTargetPath.toString(); + } + + public static boolean isImage(String contentType) { + return contentType != null && contentType.contains("image"); + } + + public static boolean isContentTypePresent(String contentType) { + return !Strings.isNullOrEmpty(contentType) && !MediaType.APPLICATION_OCTET_STREAM_VALUE.equals( + contentType); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/binary/impl/UserBinaryDataServiceImpl.java b/src/main/java/com/epam/reportportal/auth/binary/impl/UserBinaryDataServiceImpl.java new file mode 100644 index 00000000..31d59103 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/impl/UserBinaryDataServiceImpl.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary.impl; + +import static com.epam.reportportal.auth.binary.impl.DataStoreUtils.ATTACHMENT_CONTENT_TYPE; +import static com.epam.reportportal.auth.binary.impl.DataStoreUtils.PHOTOS_PATH; +import static com.epam.reportportal.auth.binary.impl.DataStoreUtils.ROOT_USER_PHOTO_DIR; +import static com.epam.reportportal.auth.binary.impl.DataStoreUtils.USER_DATA_PATH; +import static com.epam.reportportal.auth.binary.impl.DataStoreUtils.buildThumbnailFileName; +import static java.util.Optional.ofNullable; + +import com.epam.reportportal.auth.binary.DataStoreService; +import com.epam.reportportal.auth.binary.UserBinaryDataService; +import com.epam.reportportal.auth.entity.Metadata; +import com.epam.reportportal.auth.entity.attachment.BinaryData; +import com.epam.reportportal.auth.entity.enums.FeatureFlag; +import com.epam.reportportal.auth.entity.user.User; +import com.epam.reportportal.auth.util.FeatureFlagHandler; +import com.google.common.collect.Maps; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Paths; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; +import org.springframework.util.StreamUtils; + +/** + * @author Ihar Kahadouski + */ +@Service +public class UserBinaryDataServiceImpl implements UserBinaryDataService { + + private static final Logger LOGGER = LoggerFactory.getLogger(UserBinaryDataServiceImpl.class); + private static final String DEFAULT_USER_PHOTO = "image/defaultAvatar.png"; + + private final DataStoreService dataStoreService; + + private final FeatureFlagHandler featureFlagHandler; + + @Autowired + public UserBinaryDataServiceImpl( + @Qualifier("userDataStoreService") DataStoreService dataStoreService, + FeatureFlagHandler featureFlagHandler) { + this.dataStoreService = dataStoreService; + this.featureFlagHandler = featureFlagHandler; + } + + + @Override + public void saveUserPhoto(User user, BinaryData binaryData) { + saveUserPhoto(user, binaryData.getInputStream(), binaryData.getContentType()); + } + + @Override + public void saveUserPhoto(User user, InputStream inputStream, String contentType) { + try { + byte[] data = StreamUtils.copyToByteArray(inputStream); + try (InputStream userPhotoCopy = new ByteArrayInputStream(data); + InputStream thumbnailCopy = new ByteArrayInputStream(data)) { + if (featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + user.setAttachment(dataStoreService.save( + Paths.get(USER_DATA_PATH, PHOTOS_PATH, user.getLogin()).toString(), userPhotoCopy)); + user.setAttachmentThumbnail(dataStoreService.saveThumbnail( + buildThumbnailFileName(Paths.get(USER_DATA_PATH, PHOTOS_PATH).toString(), + user.getLogin() + ), thumbnailCopy)); + } else { + user.setAttachment( + dataStoreService.save(Paths.get(ROOT_USER_PHOTO_DIR, user.getLogin()).toString(), + userPhotoCopy + )); + user.setAttachmentThumbnail(dataStoreService.saveThumbnail( + buildThumbnailFileName(ROOT_USER_PHOTO_DIR, user.getLogin()), thumbnailCopy)); + } + } + ofNullable(user.getMetadata()).orElseGet(() -> new Metadata(Maps.newHashMap())).getMetadata() + .put(ATTACHMENT_CONTENT_TYPE, contentType); + } catch (IOException e) { + LOGGER.error("Unable to save user photo", e); + } + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/binary/impl/UserDataStoreService.java b/src/main/java/com/epam/reportportal/auth/binary/impl/UserDataStoreService.java new file mode 100644 index 00000000..36b830f5 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/binary/impl/UserDataStoreService.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.binary.impl; + +import com.epam.reportportal.auth.commons.Thumbnailator; +import com.epam.reportportal.auth.filesystem.DataEncoder; +import com.epam.reportportal.auth.filesystem.DataStore; +import java.io.IOException; +import java.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +/** + * @author Ihar Kahadouski + */ +@Service("userDataStoreService") +public class UserDataStoreService extends CommonDataStoreService { + + private static final Logger LOGGER = LoggerFactory.getLogger(UserDataStoreService.class); + + private final Thumbnailator thumbnailator; + + @Autowired + public UserDataStoreService(DataStore dataStore, DataEncoder dataEncoder, + @Qualifier("userPhotoThumbnailator") Thumbnailator thumbnailator) { + super(dataStore, dataEncoder); + this.thumbnailator = thumbnailator; + } + + @Override + public String saveThumbnail(String fileName, InputStream data) { + try { + return dataEncoder.encode(dataStore.save(fileName, thumbnailator.createThumbnail(data))); + } catch (IOException e) { + LOGGER.error("Thumbnail is not created for file [{}]. Error:\n", fileName, e); + } + return null; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/builder/ActivityBuilder.java b/src/main/java/com/epam/reportportal/auth/builder/ActivityBuilder.java new file mode 100644 index 00000000..1daef8aa --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/builder/ActivityBuilder.java @@ -0,0 +1,130 @@ +/* + * Copyright 2023 EPAM Systems + * + * 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 com.epam.reportportal.auth.builder; + +import com.epam.reportportal.auth.entity.activity.Activity; +import com.epam.reportportal.auth.entity.activity.ActivityDetails; +import com.epam.reportportal.auth.entity.activity.EventAction; +import com.epam.reportportal.auth.entity.activity.EventObject; +import com.epam.reportportal.auth.entity.activity.EventPriority; +import com.epam.reportportal.auth.entity.activity.EventSubject; +import com.epam.reportportal.auth.entity.activity.HistoryField; +import java.time.Instant; +import java.util.Optional; +import java.util.function.Supplier; + + +public class ActivityBuilder implements Supplier { + + public static final int MAX_OBJECT_NAME_LENGTH = 128; + private final Activity activity; + private ActivityDetails details; + + public ActivityBuilder() { + activity = new Activity(); + details = new ActivityDetails(); + } + + public ActivityBuilder addSubjectId(Long subjectId) { + activity.setSubjectId(subjectId); + return this; + } + + public ActivityBuilder addSubjectName(String postedName) { + activity.setSubjectName(postedName); + return this; + } + + public ActivityBuilder addProjectId(Long projectId) { + activity.setProjectId(projectId); + return this; + } + + public ActivityBuilder addObjectType(EventObject objectType) { + activity.setObjectType(objectType); + return this; + } + + public ActivityBuilder addAction(EventAction action) { + activity.setAction(action); + return this; + } + + public ActivityBuilder addDetails(ActivityDetails details) { + this.details = details; + return this; + } + + public ActivityBuilder addObjectName(String name) { + if (name != null && name.length() > MAX_OBJECT_NAME_LENGTH) { + name = name.substring(0, MAX_OBJECT_NAME_LENGTH - 3) + "..."; + } + activity.setObjectName(name); + return this; + } + + public ActivityBuilder addHistoryField(String field, String before, String after) { + details.addHistoryField(HistoryField.of(field, before, after)); + return this; + } + + public ActivityBuilder addHistoryField(Optional historyField) { + historyField.ifPresent(it -> details.addHistoryField(it)); + return this; + } + + public ActivityBuilder addCreatedAt(Instant instant) { + activity.setCreatedAt(instant); + return this; + } + + public ActivityBuilder addCreatedNow() { + activity.setCreatedAt(Instant.now()); + return this; + } + + public ActivityBuilder addObjectId(Long objectId) { + activity.setObjectId(objectId); + return this; + } + + public ActivityBuilder addPriority(EventPriority priority) { + activity.setPriority(priority); + return this; + } + + public ActivityBuilder addSubjectType(EventSubject eventSubject) { + activity.setSubjectType(eventSubject); + return this; + } + + public ActivityBuilder addEventName(String eventName) { + activity.setEventName(eventName); + return this; + } + + public ActivityBuilder notSavedEvent() { + activity.setSavedEvent(false); + return this; + } + + @Override + public Activity get() { + activity.setDetails(details); + return activity; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/ContentTypeResolver.java b/src/main/java/com/epam/reportportal/auth/commons/ContentTypeResolver.java new file mode 100644 index 00000000..c8abc613 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/ContentTypeResolver.java @@ -0,0 +1,58 @@ +/* + * Copyright 2016 EPAM Systems + * + * + * This file is part of EPAM Report Portal. + * https://github.com/reportportal/commons + * + * Report Portal is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Report Portal is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Report Portal. If not, see . + */ + +package com.epam.reportportal.auth.commons; + +import java.io.InputStream; +import java.nio.file.Path; + +/** + * Content type resolver + * + * @author Andrei Varabyeu + */ +public interface ContentTypeResolver { + + /** + * Detects content type of data in input stream + * + * @param data Data to be resolved + * @return detected media type, or application/octet-stream + */ + String detectContentType(byte[] data); + + /** + * Detects content type of data in input stream + * + * @param data Data to be resolved + * @return detected media type, or application/octet-stream + */ + String detectContentType(InputStream data); + + /** + * Detects content type of data in file + * + * @param data Data to be resolved + * @return detected media type, or application/octet-stream + */ + String detectContentType(Path data); + +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/EntityUtils.java b/src/main/java/com/epam/reportportal/auth/commons/EntityUtils.java new file mode 100644 index 00000000..34223728 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/EntityUtils.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons; + +import static com.google.common.base.Strings.isNullOrEmpty; +import static java.util.Optional.ofNullable; + +import com.google.common.base.Preconditions; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Date; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * Some useful utils for working with entities
For example: usernames, project names, tags, + * etc. + * + * @author Andrei Varabyeu + */ +public class EntityUtils { + + public static final Function TO_LOCAL_DATE_TIME = date -> ofNullable( + date).map(d -> LocalDateTime.ofInstant(d.toInstant(), + ZoneOffset.UTC + )).orElse(null); + + public static final Function TO_DATE = localDateTime -> ofNullable( + localDateTime).map(l -> Date.from(l.atZone( + ZoneOffset.UTC).toInstant())).orElse(null); + + public static final Function INSTANT_TO_LDT = instant -> + ofNullable(instant) + .map(i -> i.atZone(ZoneOffset.UTC).toLocalDateTime()) + .orElse(null); + + public static final Function INSTANT_TO_TIMESTAMP = instant -> + ofNullable(instant) + .map(i -> i.atZone(ZoneOffset.UTC).toLocalDateTime()) + .map(Timestamp::valueOf) + .orElse(null); + /** + * Remove leading and trailing spaces from list of string + */ + public static final Function TRIM_FUNCTION = it -> ofNullable(it).map( + String::trim).orElse(null); + public static final Predicate NOT_EMPTY = s -> !isNullOrEmpty(s); + private static final String OLD_SEPARATOR = ","; + private static final String NEW_SEPARATOR = "_"; + /** + * Convert declined symbols on allowed for WS and UI + */ + public static final Function REPLACE_SEPARATOR = s -> ofNullable(s).map( + it -> it.replace(OLD_SEPARATOR, NEW_SEPARATOR)) + .orElse(null); + + private EntityUtils() { + //static only + } + + /** + * Normalize any ID for database ID fields, for example + * + * @param id ID to normalize + * @return String + */ + + public static String normalizeId(String id) { + return Preconditions.checkNotNull(id, "Provided value shouldn't be null").toLowerCase(); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/JsonbAwarePostgresDialect.java b/src/main/java/com/epam/reportportal/auth/commons/JsonbAwarePostgresDialect.java new file mode 100644 index 00000000..6bbf3648 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/JsonbAwarePostgresDialect.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons; + +import java.sql.Types; +import org.hibernate.dialect.PostgreSQL95Dialect; + +/** + * Postgres Dialect aware of JSON/JSONB types + * + * @author Andrei Varabyeu + */ +public class JsonbAwarePostgresDialect extends PostgreSQL95Dialect { + + public JsonbAwarePostgresDialect() { + super(); + this.registerColumnType(Types.JAVA_OBJECT, "json"); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/JsonbUserType.java b/src/main/java/com/epam/reportportal/auth/commons/JsonbUserType.java new file mode 100644 index 00000000..7aafb491 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/JsonbUserType.java @@ -0,0 +1,152 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons; + +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.SerializationException; +import org.hibernate.usertype.UserType; +import org.postgresql.util.PGobject; +import org.springframework.util.ObjectUtils; + +/** + * @author Pavel Bortnik + */ +public abstract class JsonbUserType implements UserType { + + private final ObjectMapper mapper; + + public JsonbUserType() { + mapper = new ObjectMapper(); + mapper.registerModule(new JavaTimeModule()); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + @Override + public int[] sqlTypes() { + return new int[]{Types.JAVA_OBJECT}; + } + + @Override + abstract public Class returnedClass(); + + @Override + public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, + Object owner) + throws HibernateException, SQLException { + if (rs.getObject(names[0]) == null) { + return null; + } + PGobject pgObject = (PGobject) rs.getObject(names[0]); + try { + return mapper.readValue(pgObject.getValue(), this.returnedClass()); + } catch (Exception e) { + throw new ReportPortalException("Failed to convert String to Invoice: " + e.getMessage(), e); + } + } + + @Override + public void nullSafeSet(PreparedStatement st, Object value, int index, + SharedSessionContractImplementor session) + throws HibernateException, SQLException { + if (value == null) { + st.setNull(index, Types.OTHER); + return; + } + try { + PGobject pGobject = new PGobject(); + pGobject.setType("jsonb"); + pGobject.setValue(mapper.writeValueAsString(value)); + st.setObject(index, pGobject); + } catch (final Exception ex) { + throw new ReportPortalException("Failed to convert Invoice to String: " + ex.getMessage(), + ex); + } + + } + + @Override + public Object deepCopy(Object value) throws HibernateException { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( + bos)) { + // use serialization to create a deep copy + + oos.writeObject(value); + oos.flush(); + + ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); + return new ObjectInputStream(bais).readObject(); + } catch (ClassNotFoundException | IOException ex) { + throw new HibernateException(ex); + } + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + Object copy = deepCopy(value); + if (copy instanceof Serializable) { + return (Serializable) copy; + } + throw new SerializationException( + String.format("Cannot serialize '%s', %s is not Serializable.", value, value.getClass()), + null); + } + + @Override + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return deepCopy(cached); + } + + @Override + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return deepCopy(original); + } + + @Override + @JsonIgnore + public boolean isMutable() { + return true; + } + + @Override + public int hashCode(Object x) throws HibernateException { + if (x == null) { + return 0; + } + return x.hashCode(); + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + return ObjectUtils.nullSafeEquals(x, y); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/Predicates.java b/src/main/java/com/epam/reportportal/auth/commons/Predicates.java new file mode 100644 index 00000000..a6af751a --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/Predicates.java @@ -0,0 +1,76 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * @author dzmitry_kavalets + */ +public class Predicates { + + private Predicates() { + //statics only + } + + public static Predicate notNull() { + return Objects::nonNull; + } + + public static Predicate isNull() { + return Objects::isNull; + } + + public static Predicate equalTo(T target) { + return (target == null) ? Predicates.isNull() : t -> t.equals(target); + } + + public static Predicate not(Predicate predicate) { + return item -> !predicate.test(item); + } + + public static Predicate in(Collection target) { + return target::contains; + } + + public static Predicate alwaysFalse() { + return t -> false; + } + + public static Predicate and(List> components) { + return t -> components.stream().allMatch(predicate -> predicate.test(t)); + } + + @SuppressWarnings("unchecked") + public static Predicate or(Predicate... components) { + return t -> Stream.of(components).anyMatch(predicate -> predicate.test(t)); + } + + public static Predicate or(Iterable> components) { + return t -> StreamSupport.stream(components.spliterator(), false) + .anyMatch(predicate -> predicate.test(t)); + } + + public static Predicate> isPresent() { + return Optional::isPresent; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/ReportPortalUser.java b/src/main/java/com/epam/reportportal/auth/commons/ReportPortalUser.java new file mode 100644 index 00000000..780a9828 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/ReportPortalUser.java @@ -0,0 +1,263 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons; + +import static java.util.Optional.ofNullable; + +import com.epam.reportportal.auth.entity.project.ProjectRole; +import com.epam.reportportal.auth.entity.user.UserRole; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * ReportPortal user representation + * + * @author Andrei Varabyeu + */ +public class ReportPortalUser extends User { + + private boolean active; + + private Long userId; + + private UserRole userRole; + + private String email; + + private Map projectDetails; + + private ReportPortalUser(String username, String password, + Collection authorities, Long userId, + UserRole role, Map projectDetails, String email, boolean isActive) { + super(username, password, authorities); + this.userId = userId; + this.userRole = role; + this.projectDetails = projectDetails; + this.email = email; + this.active = isActive; + } + + public static ReportPortalUserBuilder userBuilder() { + return new ReportPortalUserBuilder(); + } + + @Override + public boolean isEnabled() { + return active; + } + + @Override + public boolean isAccountNonLocked() { + return active; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public UserRole getUserRole() { + return userRole; + } + + public void setUserRole(UserRole userRole) { + this.userRole = userRole; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Map getProjectDetails() { + return projectDetails; + } + + public void setProjectDetails(Map projectDetails) { + this.projectDetails = projectDetails; + } + + public static class ProjectDetails implements Serializable { + + @JsonProperty(value = "id") + private Long projectId; + + @JsonProperty(value = "name") + private String projectName; + + @JsonProperty("role") + private ProjectRole projectRole; + + public ProjectDetails(Long projectId, String projectName, ProjectRole projectRole) { + this.projectId = projectId; + this.projectName = projectName; + this.projectRole = projectRole; + } + + public static ProjectDetailsBuilder builder() { + return new ProjectDetailsBuilder(); + } + + public Long getProjectId() { + return projectId; + } + + public String getProjectName() { + return projectName; + } + + public ProjectRole getProjectRole() { + return projectRole; + } + + public static class ProjectDetailsBuilder { + + private Long projectId; + private String projectName; + private ProjectRole projectRole; + + private ProjectDetailsBuilder() { + } + + public ProjectDetailsBuilder withProjectId(Long projectId) { + this.projectId = projectId; + return this; + } + + public ProjectDetailsBuilder withProjectName(String projectName) { + this.projectName = projectName; + return this; + } + + public ProjectDetailsBuilder withProjectRole(String projectRole) { + this.projectRole = ProjectRole.forName(projectRole) + .orElseThrow(() -> new ReportPortalException(ErrorType.ROLE_NOT_FOUND, projectRole)); + return this; + } + + public ProjectDetails build() { + return new ProjectDetails(projectId, projectName, projectRole); + } + } + } + + public static class ReportPortalUserBuilder { + + private boolean active; + private String username; + private String password; + private Long userId; + private UserRole userRole; + private String email; + private Map projectDetails; + private Collection authorities; + + private ReportPortalUserBuilder() { + + } + + public ReportPortalUserBuilder withActive(boolean active) { + this.active = active; + return this; + } + + public ReportPortalUserBuilder withUserName(String userName) { + this.username = userName; + return this; + } + + public ReportPortalUserBuilder withPassword(String password) { + this.password = password; + return this; + } + + public ReportPortalUserBuilder withAuthorities( + Collection authorities) { + this.authorities = authorities; + return this; + } + + public ReportPortalUserBuilder withUserDetails(UserDetails userDetails) { + this.username = userDetails.getUsername(); + this.password = userDetails.getPassword(); + this.authorities = userDetails.getAuthorities(); + this.active = userDetails.isEnabled(); + return this; + } + + public ReportPortalUserBuilder withUserId(Long userId) { + this.userId = userId; + return this; + } + + public ReportPortalUserBuilder withUserRole(UserRole userRole) { + this.userRole = userRole; + return this; + } + + public ReportPortalUserBuilder withEmail(String email) { + this.email = email; + return this; + } + + public ReportPortalUserBuilder withProjectDetails(Map projectDetails) { + this.projectDetails = projectDetails; + return this; + } + + public ReportPortalUser fromUser(com.epam.reportportal.auth.entity.user.User user) { + this.active = user.getActive(); + this.username = user.getLogin(); + this.email = user.getPassword(); + this.userId = user.getId(); + this.userRole = user.getRole(); + this.password = ofNullable(user.getPassword()).orElse(""); + this.authorities = Collections.singletonList( + new SimpleGrantedAuthority(user.getRole().getAuthority())); + this.projectDetails = user.getProjects().stream().collect(Collectors.toMap( + it -> it.getProject().getName(), + it -> ProjectDetails.builder() + .withProjectId(it.getProject().getId()) + .withProjectRole(it.getProjectRole().name()) + .withProjectName(it.getProject().getName()) + .build() + )); + return build(); + } + + public ReportPortalUser build() { + return new ReportPortalUser(username, password, authorities, userId, userRole, projectDetails, + email, active); + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/Thumbnailator.java b/src/main/java/com/epam/reportportal/auth/commons/Thumbnailator.java new file mode 100644 index 00000000..f78b665e --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/Thumbnailator.java @@ -0,0 +1,51 @@ +/* + * Copyright 2016 EPAM Systems + * + * + * This file is part of EPAM Report Portal. + * https://github.com/reportportal/commons + * + * Report Portal is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Report Portal is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Report Portal. If not, see . + */ + +package com.epam.reportportal.auth.commons; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Creates Thumbnails of images + * + * @author Andrei Varabyeu + */ +public interface Thumbnailator { + + /** + * Creates thumbnail of provided image + * + * @param is - Image's InputStream + * @return - Thumbnail's InputStream + * @throws IOException IO exception + */ + InputStream createThumbnail(InputStream is) throws IOException; + + /** + * Creates thumbnail of provided image + * + * @param data Image to be Thumbnailed + * @return Thumbnail of image + * @throws IOException IO exception + */ + byte[] createThumbnail(byte[] data) throws IOException; +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/ThumbnailatorImpl.java b/src/main/java/com/epam/reportportal/auth/commons/ThumbnailatorImpl.java new file mode 100644 index 00000000..47aef468 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/ThumbnailatorImpl.java @@ -0,0 +1,73 @@ +/* + * Copyright 2016 EPAM Systems + * + * + * This file is part of EPAM Report Portal. + * https://github.com/reportportal/commons + * + * Report Portal is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Report Portal is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Report Portal. If not, see . + */ + +package com.epam.reportportal.auth.commons; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import net.coobird.thumbnailator.Thumbnails; + +/** + * Thumbnailator implementation. Using Thumbnailator API. + * + * @author Andrei Varabyeu + */ +public class ThumbnailatorImpl implements Thumbnailator { + + // 80 + private int width = 80; + + // 60 + private int height = 60; + + /** + * With default sizes + */ + public ThumbnailatorImpl() { + + } + + public ThumbnailatorImpl(int width, int height) { + this.width = width; + this.height = height; + } + + @Override + public InputStream createThumbnail(InputStream is) throws IOException { + try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + Thumbnails.of(is).size(width, height).toOutputStream(baos); + return new ByteArrayInputStream(baos.toByteArray()); + } + } + + @Override + public byte[] createThumbnail(byte[] data) throws IOException { + try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + Thumbnails.of(new ByteArrayInputStream(data)).size(width, height) + .toOutputStream(baos); + return baos.toByteArray(); + } + + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/TikaContentTypeResolver.java b/src/main/java/com/epam/reportportal/auth/commons/TikaContentTypeResolver.java new file mode 100644 index 00000000..de09add5 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/TikaContentTypeResolver.java @@ -0,0 +1,74 @@ +/* + * Copyright 2016 EPAM Systems + * + * + * This file is part of EPAM Report Portal. + * https://github.com/reportportal/commons + * + * Report Portal is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Report Portal is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Report Portal. If not, see . + */ + +package com.epam.reportportal.auth.commons; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import org.apache.tika.detect.Detector; +import org.apache.tika.io.TikaInputStream; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.AutoDetectParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class TikaContentTypeResolver implements ContentTypeResolver { + + private static final Logger LOGGER = LoggerFactory.getLogger(TikaContentTypeResolver.class); + + @Override + public String detectContentType(byte[] data) { + return detectContentType(new ByteArrayInputStream(data)); + } + + @Override + public String detectContentType(InputStream data) { + return detectContentType(TikaInputStream.get(data)); + } + + @Override + public String detectContentType(Path data) { + try { + return detectContentType(TikaInputStream.get(data)); + } catch (IOException e) { + LOGGER.error("Cannot read data stream", e); + return MediaType.OCTET_STREAM.toString(); + } + } + + private String detectContentType(TikaInputStream is) { + try { + AutoDetectParser parser = new AutoDetectParser(); + Detector detector = parser.getDetector(); + MediaType mediaType = detector.detect(is, new Metadata()); + return mediaType.toString(); + } catch (IOException e) { + LOGGER.error("Cannot read data stream", e); + return MediaType.OCTET_STREAM.toString(); + } + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/accessible/Accessible.java b/src/main/java/com/epam/reportportal/auth/commons/accessible/Accessible.java new file mode 100644 index 00000000..ba10c3b0 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/accessible/Accessible.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons.accessible; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Representation of accessible method or field + * + * @author Andrei Varabyeu + */ +public class Accessible { + + private final Object object; + + private Accessible(Object object) { + this.object = object; + + } + + public static Accessible on(Object object) { + return new Accessible(object); + } + + public AccessibleMethod method(Method m) { + return new AccessibleMethod(object, m); + } + + public AccessibleField field(Field f) { + return new AccessibleField(object, f); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/accessible/AccessibleField.java b/src/main/java/com/epam/reportportal/auth/commons/accessible/AccessibleField.java new file mode 100644 index 00000000..d26606aa --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/accessible/AccessibleField.java @@ -0,0 +1,65 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons.accessible; + +import java.lang.reflect.Field; + +/** + * Setter and Getter for Accessible Field + * + * @author Andrei Varabyeu + */ +public class AccessibleField { + + private final Field f; + private final Object bean; + + AccessibleField(Object bean, Field f) { + this.bean = bean; + this.f = f; + } + + public Class getType() { + return this.f.getType(); + } + + public Object getValue() { + try { + return this.f.get(this.bean); + } catch (IllegalAccessException accessException) { //NOSONAR + this.f.setAccessible(true); + try { + return this.f.get(this.bean); + } catch (IllegalAccessException e) { //NOSONAR + throw new IllegalAccessError(e.getMessage()); + } + } + } + + public void setValue(Object value) { + try { + this.f.set(this.bean, value); + } catch (IllegalAccessException accessException) { //NOSONAR + this.f.setAccessible(true); + try { + this.f.set(this.bean, value); + } catch (IllegalAccessException e) { //NOSONAR + throw new IllegalAccessError(e.getMessage()); + } + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/commons/accessible/AccessibleMethod.java b/src/main/java/com/epam/reportportal/auth/commons/accessible/AccessibleMethod.java new file mode 100644 index 00000000..943668ab --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/commons/accessible/AccessibleMethod.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.commons.accessible; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Accessible method implementation. Set accessibility == true for specified method and can invoke + * methods + * + * @author Andrei Varabyeu + */ +public class AccessibleMethod { + + private final Method method; + private final Object bean; + + AccessibleMethod(Object bean, Method method) { + this.bean = bean; + this.method = method; + } + + public Object invoke(Object... args) throws Throwable { + try { + return invoke(this.bean, this.method, args); + } catch (IllegalAccessException accessException) { //NOSONAR + this.method.setAccessible(true); + try { + return invoke(this.bean, this.method, args); + } catch (IllegalAccessException e) { //NOSONAR + throw new IllegalAccessError(e.getMessage()); + } + } + + } + + private Object invoke(Object bean, Method m, Object... args) throws Throwable { + try { + return m.invoke(bean, args); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/config/DataSourceConfig.java b/src/main/java/com/epam/reportportal/auth/config/DataSourceConfig.java new file mode 100644 index 00000000..afde93ab --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/config/DataSourceConfig.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.config; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import javax.sql.DataSource; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * @author Ihar Kahadouski + */ +@Configuration +@ConfigurationProperties(prefix = "rp.datasource") +public class DataSourceConfig extends HikariConfig { + + @Primary + @Bean + public DataSource dataSource() { + return new HikariDataSource(this); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/config/DataStoreConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/DataStoreConfiguration.java new file mode 100644 index 00000000..6f079f64 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/config/DataStoreConfiguration.java @@ -0,0 +1,253 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.config; + +import com.epam.reportportal.auth.commons.Thumbnailator; +import com.epam.reportportal.auth.commons.ThumbnailatorImpl; +import com.epam.reportportal.auth.filesystem.DataStore; +import com.epam.reportportal.auth.filesystem.LocalDataStore; +import com.epam.reportportal.auth.filesystem.distributed.s3.S3DataStore; +import com.epam.reportportal.auth.util.FeatureFlagHandler; +import com.google.common.base.Optional; +import com.google.common.base.Supplier; +import com.google.common.cache.CacheLoader; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.inject.Module; +import java.util.Properties; +import java.util.Set; +import org.jclouds.ContextBuilder; +import org.jclouds.aws.s3.config.AWSS3HttpApiModule; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.filesystem.reference.FilesystemConstants; +import org.jclouds.rest.ConfiguresHttpApi; +import org.jclouds.s3.S3Client; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Dzianis_Shybeka + */ +@Configuration +public class DataStoreConfiguration { + + /** + * Amazon has a general work flow they publish that allows clients to always find the correct URL + * endpoint for a given bucket: 1) ask s3.amazonaws.com for the bucket location 2) use the url + * returned to make the container specific request (get/put, etc) Jclouds cache the results from + * the first getBucketLocation call and use that region-specific URL, as needed. In this custom + * implementation of {@link AWSS3HttpApiModule} we are providing location from environment + * variable, so that we don't need to make getBucketLocation call + */ + @ConfiguresHttpApi + private static class CustomBucketToRegionModule extends AWSS3HttpApiModule { + + private final String region; + + public CustomBucketToRegionModule(String region) { + this.region = region; + } + + @Override + @SuppressWarnings("Guava") + protected CacheLoader> bucketToRegion( + Supplier> regionSupplier, S3Client client) { + Set regions = regionSupplier.get(); + if (regions.isEmpty()) { + return new CacheLoader<>() { + + @Override + @SuppressWarnings({"Guava", "NullableProblems"}) + public Optional load(String bucket) { + if (CustomBucketToRegionModule.this.region != null) { + return Optional.of(CustomBucketToRegionModule.this.region); + } + return Optional.absent(); + } + + @Override + public String toString() { + return "noRegions()"; + } + }; + } else if (regions.size() == 1) { + final String onlyRegion = Iterables.getOnlyElement(regions); + return new CacheLoader<>() { + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + final Optional onlyRegionOption = Optional.of(onlyRegion); + + @Override + @SuppressWarnings("NullableProblems") + public Optional load(String bucket) { + if (CustomBucketToRegionModule.this.region != null) { + return Optional.of(CustomBucketToRegionModule.this.region); + } + return onlyRegionOption; + } + + @Override + public String toString() { + return "onlyRegion(" + onlyRegion + ")"; + } + }; + } else { + return new CacheLoader<>() { + @Override + @SuppressWarnings("NullableProblems") + public Optional load(String bucket) { + if (CustomBucketToRegionModule.this.region != null) { + return Optional.of(CustomBucketToRegionModule.this.region); + } + try { + return Optional.fromNullable(client.getBucketLocation(bucket)); + } catch (ContainerNotFoundException e) { + return Optional.absent(); + } + } + + @Override + public String toString() { + return "bucketToRegion()"; + } + }; + } + } + } + + @Bean + @ConditionalOnProperty(name = "datastore.type", havingValue = "filesystem") + public BlobStore filesystemBlobStore( + @Value("${datastore.path:/data/store}") String baseDirectory) { + + Properties properties = new Properties(); + properties.setProperty(FilesystemConstants.PROPERTY_BASEDIR, baseDirectory); + + BlobStoreContext blobStoreContext = + ContextBuilder.newBuilder("filesystem").overrides(properties) + .buildView(BlobStoreContext.class); + + return blobStoreContext.getBlobStore(); + } + + @Bean + @ConditionalOnProperty(name = "datastore.type", havingValue = "filesystem") + public DataStore localDataStore(@Autowired BlobStore blobStore, + FeatureFlagHandler featureFlagHandler, + @Value("${datastore.bucketPrefix}") String bucketPrefix, + @Value("${datastore.bucketPostfix}") String bucketPostfix, + @Value("${datastore.defaultBucketName}") String defaultBucketName) { + return new LocalDataStore( + blobStore, featureFlagHandler, bucketPrefix, bucketPostfix, defaultBucketName); + } + + /** + * Creates BlobStore bean, that works with MinIO. + * + * @param accessKey accessKey to use + * @param secretKey secretKey to use + * @param endpoint MinIO endpoint + * @return {@link BlobStore} + */ + @Bean + @ConditionalOnProperty(name = "datastore.type", havingValue = "minio") + public BlobStore minioBlobStore(@Value("${datastore.accessKey}") String accessKey, + @Value("${datastore.secretKey}") String secretKey, + @Value("${datastore.endpoint}") String endpoint) { + + BlobStoreContext blobStoreContext = ContextBuilder.newBuilder("s3") + .endpoint(endpoint) + .credentials(accessKey, secretKey) + .buildView(BlobStoreContext.class); + + return blobStoreContext.getBlobStore(); + } + + /** + * Creates DataStore bean to work with MinIO. + * + * @param blobStore {@link BlobStore} object + * @param bucketPrefix Prefix for bucket name + * @param defaultBucketName Name of default bucket to use + * @param region Region to store + * @param featureFlagHandler Instance of {@link FeatureFlagHandler} to check enabled features + * @return {@link DataStore} object + */ + @Bean + @ConditionalOnProperty(name = "datastore.type", havingValue = "minio") + public DataStore minioDataStore(@Autowired BlobStore blobStore, + @Value("${datastore.bucketPrefix}") String bucketPrefix, + @Value("${datastore.bucketPostfix}") String bucketPostfix, + @Value("${datastore.defaultBucketName}") String defaultBucketName, + @Value("${datastore.region}") String region, FeatureFlagHandler featureFlagHandler) { + return new S3DataStore( + blobStore, bucketPrefix, bucketPostfix, defaultBucketName, region, featureFlagHandler); + } + + /** + * Creates BlobStore bean, that works with AWS S3. + * + * @param accessKey accessKey to use + * @param secretKey secretKey to use + * @param region AWS S3 region to use. + * @return {@link BlobStore} + */ + @Bean + @ConditionalOnProperty(name = "datastore.type", havingValue = "s3") + public BlobStore s3BlobStore(@Value("${datastore.accessKey}") String accessKey, + @Value("${datastore.secretKey}") String secretKey, + @Value("${datastore.region}") String region) { + Iterable modules = ImmutableSet.of(new CustomBucketToRegionModule(region)); + + BlobStoreContext blobStoreContext = + ContextBuilder.newBuilder("aws-s3").modules(modules).credentials(accessKey, secretKey) + .buildView(BlobStoreContext.class); + + return blobStoreContext.getBlobStore(); + } + + @Bean + @ConditionalOnProperty(name = "datastore.type", havingValue = "s3") + public DataStore s3DataStore(@Autowired BlobStore blobStore, + @Value("${datastore.bucketPrefix}") String bucketPrefix, + @Value("${datastore.bucketPostfix}") String bucketPostfix, + @Value("${datastore.defaultBucketName}") String defaultBucketName, + @Value("${datastore.region}") String region, FeatureFlagHandler featureFlagHandler) { + return new S3DataStore(blobStore, bucketPrefix, bucketPostfix, defaultBucketName, region, + featureFlagHandler + ); + } + + @Bean("attachmentThumbnailator") + public Thumbnailator attachmentThumbnailator( + @Value("${datastore.thumbnail.attachment.width}") int width, + @Value("${datastore.thumbnail.attachment.height}") int height) { + return new ThumbnailatorImpl(width, height); + } + + @Bean("userPhotoThumbnailator") + public Thumbnailator userPhotoThumbnailator( + @Value("${datastore.thumbnail.avatar.width}") int width, + @Value("${datastore.thumbnail.avatar.height}") int height) { + return new ThumbnailatorImpl(width, height); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/config/DatabaseConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/DatabaseConfiguration.java new file mode 100644 index 00000000..0d31dfbf --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/config/DatabaseConfiguration.java @@ -0,0 +1,138 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.config; + +import com.epam.reportportal.auth.dao.ReportPortalRepositoryImpl; +import java.io.Serializable; +import java.util.Properties; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.repository.support.JpaEntityInformation; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; +import org.springframework.data.jpa.repository.support.JpaRepositoryImplementation; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.core.RepositoryInformation; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.util.Assert; + +/** + * @author Pavel Bortnik + */ +@Configuration +@EnableJpaAuditing +@EnableJpaRepositories(basePackages = { + "com.epam.reportportal.auth.dao"}, repositoryBaseClass = ReportPortalRepositoryImpl.class, repositoryFactoryBeanClass = DatabaseConfiguration.RpRepoFactoryBean.class) +@EnableTransactionManagement +@EnableCaching +public class DatabaseConfiguration { + + @Autowired + private DataSource dataSource; + + @Bean + public EntityManagerFactory entityManagerFactory() { + + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setGenerateDdl(false); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan("com.epam.reportportal.auth.commons", + "com.epam.reportportal.auth.entity"); + factory.setDataSource(dataSource); + + Properties jpaProperties = new Properties(); + jpaProperties.setProperty("hibernate.dialect", + "com.epam.reportportal.auth.commons.JsonbAwarePostgresDialect"); + factory.setJpaProperties(jpaProperties); + + factory.afterPropertiesSet(); + + return factory.getObject(); + } + + @Bean + @Primary + public PlatformTransactionManager transactionManager() { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory()); + return transactionManager; + } + + @Bean + public TransactionAwareDataSourceProxy transactionAwareDataSource() { + return new TransactionAwareDataSourceProxy(dataSource); + } + + + public static class RpRepoFactoryBean, S, ID> extends + JpaRepositoryFactoryBean { + + @Autowired + private AutowireCapableBeanFactory beanFactory; + + /** + * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. + * + * @param repositoryInterface must not be {@literal null}. + */ + public RpRepoFactoryBean(Class repositoryInterface) { + super(repositoryInterface); + } + + @Override + protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { + return new JpaRepositoryFactory(entityManager) { + @Override + public T getRepository(Class repositoryInterface) { + T repo = super.getRepository(repositoryInterface); + beanFactory.autowireBean(repo); + return repo; + } + + @Override + protected JpaRepositoryImplementation getTargetRepository( + RepositoryInformation information, EntityManager em) { + + JpaEntityInformation entityInformation = getEntityInformation( + information.getDomainType()); + Object repository = getTargetRepositoryViaReflection(information, entityInformation, em); + + Assert.isInstanceOf(JpaRepositoryImplementation.class, repository); + beanFactory.autowireBean(repository); + return (JpaRepositoryImplementation) repository; + } + }; + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/config/EncryptConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/EncryptConfiguration.java new file mode 100644 index 00000000..866b387c --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/config/EncryptConfiguration.java @@ -0,0 +1,138 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.config; + +import static com.epam.reportportal.auth.binary.impl.DataStoreUtils.INTEGRATION_SECRETS_PATH; + +import com.epam.reportportal.auth.entity.enums.FeatureFlag; +import com.epam.reportportal.auth.filesystem.DataStore; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.epam.reportportal.auth.util.FeatureFlagHandler; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.security.SecureRandom; +import java.util.Base64; +import java.util.Optional; +import org.apache.commons.io.IOUtils; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; +import org.jasypt.util.text.BasicTextEncryptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Encrypt beans configuration for password values + * + * @author Andrei_Ramanchuk + */ +@Configuration +public class EncryptConfiguration implements InitializingBean { + + private static final Logger LOGGER = LoggerFactory.getLogger(EncryptConfiguration.class); + + @Value("${rp.encryptor.password:#{null}}") + private String password; + + @Value("${rp.integration.salt.path:keystore}") + private String passwordFilePath; + + @Value("${rp.integration.salt.file:secret-integration-salt}") + private String passwordFile; + + private String secretFilePath; + + private final DataStore dataStore; + + private final FeatureFlagHandler featureFlagHandler; + + @Autowired + public EncryptConfiguration(DataStore dataStore, FeatureFlagHandler featureFlagHandler) { + this.dataStore = dataStore; + this.featureFlagHandler = featureFlagHandler; + } + + /** + * Creates bean of {@link BasicTextEncryptor} for encrypting purposes. + * + * @return {@link BasicTextEncryptor} instance + */ + @Bean//(name = "basicEncryptor") + public BasicTextEncryptor basicTextEncryptor() { + BasicTextEncryptor basic = new BasicTextEncryptor(); + basic.setPassword(getPassword()); + return basic; + } + + /** + * Creates bean of {@link StandardPBEStringEncryptor} for encrypting purposes. + * + * @return {@link StandardPBEStringEncryptor} instance + */ + @Bean(name = "strongEncryptor") + public StandardPBEStringEncryptor getStrongEncryptor() { + StandardPBEStringEncryptor strong = new StandardPBEStringEncryptor(); + strong.setPassword(getPassword()); + strong.setAlgorithm("PBEWithMD5AndTripleDES"); + return strong; + } + + @Override + public void afterPropertiesSet() { + if (featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + secretFilePath = Paths.get(INTEGRATION_SECRETS_PATH, passwordFile).toString(); + } else { + secretFilePath = passwordFilePath + File.separator + passwordFile; + } + if (password == null) { + loadOrGenerateEncryptorPassword(); + } + } + + private String getPassword() { + return Optional.ofNullable(password).orElseGet(this::loadFromDataStore); + } + + private String loadFromDataStore() { + try (InputStream source = dataStore.load(secretFilePath)) { + return IOUtils.toString(source, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, e.getMessage()); + } + } + + private void loadOrGenerateEncryptorPassword() { + if (!dataStore.exists(secretFilePath)) { + byte[] bytes = new byte[20]; + new SecureRandom().nextBytes(bytes); + try (InputStream secret = new ByteArrayInputStream( + Base64.getUrlEncoder().withoutPadding().encode(bytes))) { + dataStore.save(secretFilePath, secret); + } catch (IOException ioEx) { + LOGGER.error("Unable to generate secret file", ioEx); + } + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/config/SecurityConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/SecurityConfiguration.java index d9f4bf91..6838bf72 100644 --- a/src/main/java/com/epam/reportportal/auth/config/SecurityConfiguration.java +++ b/src/main/java/com/epam/reportportal/auth/config/SecurityConfiguration.java @@ -20,6 +20,9 @@ import com.epam.reportportal.auth.ReportPortalClient; import com.epam.reportportal.auth.basic.BasicPasswordAuthenticationProvider; import com.epam.reportportal.auth.basic.DatabaseUserDetailsService; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.ServerSettingsRepository; +import com.epam.reportportal.auth.entity.ServerSettings; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.github.ExternalOauth2TokenConverter; import com.epam.reportportal.auth.integration.ldap.ActiveDirectoryAuthProvider; @@ -28,11 +31,8 @@ import com.epam.reportportal.auth.integration.ldap.LdapUserReplicator; import com.epam.reportportal.auth.integration.parameter.ParameterUtils; import com.epam.reportportal.auth.oauth.OAuthProvider; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.ServerSettingsRepository; -import com.epam.ta.reportportal.entity.ServerSettings; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import com.google.common.collect.ImmutableList; import java.util.Arrays; import java.util.Collections; @@ -53,6 +53,7 @@ import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotatedTypeMetadata; @@ -238,19 +239,19 @@ protected final void configure(HttpSecurity http) throws Exception { authCompositeFilter.setFilters(additionalFilters); http - .antMatcher("/**") - .authorizeRequests() - .antMatchers(SSO_LOGIN_PATH - + "/**", "/epam/**", "/info", "/health", "/api-docs/**", "/saml/**", "/templates/**") - .permitAll() - .anyRequest() - .authenticated() - .and() - .csrf().disable() - .formLogin().disable() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() + .antMatcher("/**") + .authorizeRequests() + .antMatchers(SSO_LOGIN_PATH + + "/**", "/epam/**", "/info", "/health", "/api-docs/**", "/saml/**", "/templates/**") + .permitAll() + .anyRequest() + .authenticated() + .and() + .csrf().disable() + .formLogin().disable() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() .addFilterAfter(authCompositeFilter, BasicAuthenticationFilter.class); } @@ -280,7 +281,6 @@ public AuthenticationEventPublisher authenticationEventPublisher( } - @Bean public AuthenticationProvider activeDirectoryAuthProvider() { return new ActiveDirectoryAuthProvider(authConfigRepository, eventPublisher, @@ -420,6 +420,7 @@ public AccessTokenConverter externalOauth2TokenConverter( } @Bean + @Profile("!unittest") public JwtAccessTokenConverter accessTokenConverter(AccessTokenConverter accessTokenConverter) { JwtAccessTokenConverter jwtConverter = new JwtAccessTokenConverter(); jwtConverter.setSigningKey(getSecret()); diff --git a/src/main/java/com/epam/reportportal/auth/config/SpringDocConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/SpringDocConfiguration.java index b6739dc4..b6fa919f 100644 --- a/src/main/java/com/epam/reportportal/auth/config/SpringDocConfiguration.java +++ b/src/main/java/com/epam/reportportal/auth/config/SpringDocConfiguration.java @@ -16,10 +16,8 @@ package com.epam.reportportal.auth.config; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.ta.reportportal.commons.querygen.Filter; -import com.epam.ta.reportportal.commons.querygen.Queryable; -import com.epam.ta.reportportal.entity.user.UserRole; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.entity.user.UserRole; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; @@ -55,8 +53,7 @@ public class SpringDocConfiguration { static { SpringDocUtils.getConfig().addAnnotationsToIgnore(AuthenticationPrincipal.class); - SpringDocUtils.getConfig().addRequestWrapperToIgnore(Filter.class, Queryable.class, - ReportPortalUser.class, UserRole.class); + SpringDocUtils.getConfig().addRequestWrapperToIgnore(ReportPortalUser.class, UserRole.class); SpringDocUtils.getConfig().replaceWithClass(org.springframework.data.domain.Pageable.class, org.springdoc.core.converters.models.Pageable.class); } @@ -82,7 +79,7 @@ public OpenAPI openAPI() { .email("support@reportportal.io") ) .license(new License().name("Apache 2.0") - .url("http://www.apache.org/licenses/LICENSE-2.0"))) + .url("https://www.apache.org/licenses/LICENSE-2.0"))) .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) .components( new Components() @@ -116,6 +113,6 @@ public OpenApiCustomiser sortTagsAlphabetically() { } private String getPathValue() { - return StringUtils.isEmpty(pathValue) || pathValue.equals("/") ? "/uat" : pathValue; + return StringUtils.isEmpty(pathValue) || pathValue.equals("/") ? "/uat" : pathValue; } } diff --git a/src/main/java/com/epam/reportportal/auth/config/WebMvcConfig.java b/src/main/java/com/epam/reportportal/auth/config/WebMvcConfig.java index 1513d5f6..01a3577d 100644 --- a/src/main/java/com/epam/reportportal/auth/config/WebMvcConfig.java +++ b/src/main/java/com/epam/reportportal/auth/config/WebMvcConfig.java @@ -17,13 +17,13 @@ package com.epam.reportportal.auth.config; -import com.epam.reportportal.rules.commons.ExceptionMappings; -import com.epam.reportportal.rules.commons.exception.message.DefaultExceptionMessageBuilder; -import com.epam.reportportal.rules.commons.exception.rest.DefaultErrorResolver; -import com.epam.reportportal.rules.commons.exception.rest.ReportPortalExceptionResolver; -import com.epam.reportportal.rules.commons.exception.rest.RestErrorDefinition; -import com.epam.reportportal.rules.commons.exception.rest.RestExceptionHandler; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.commons.ExceptionMappings; +import com.epam.reportportal.auth.rules.commons.exception.message.DefaultExceptionMessageBuilder; +import com.epam.reportportal.auth.rules.commons.exception.rest.DefaultErrorResolver; +import com.epam.reportportal.auth.rules.commons.exception.rest.ReportPortalExceptionResolver; +import com.epam.reportportal.auth.rules.commons.exception.rest.RestErrorDefinition; +import com.epam.reportportal.auth.rules.commons.exception.rest.RestExceptionHandler; +import com.epam.reportportal.auth.rules.exception.ErrorType; import com.google.common.collect.ImmutableMap; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/epam/reportportal/auth/config/saml/SamlSecurityConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/saml/SamlSecurityConfiguration.java index 95394895..d998585b 100644 --- a/src/main/java/com/epam/reportportal/auth/config/saml/SamlSecurityConfiguration.java +++ b/src/main/java/com/epam/reportportal/auth/config/saml/SamlSecurityConfiguration.java @@ -32,7 +32,7 @@ @Order(4) public class SamlSecurityConfiguration extends SamlServiceProviderSecurityConfiguration { - private SamlServerConfiguration serverConfiguration; + private final SamlServerConfiguration serverConfiguration; public SamlSecurityConfiguration(SamlServiceProviderServerBeanConfiguration configuration, SamlServerConfiguration spConfiguration) { diff --git a/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderBeanConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderBeanConfiguration.java index abdaf32d..945e4213 100644 --- a/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderBeanConfiguration.java +++ b/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderBeanConfiguration.java @@ -61,10 +61,10 @@ public class SamlServiceProviderBeanConfiguration extends private final Integer maxSessionLive; - private SamlAuthSuccessHandler samlSuccessHandler; - private AuthFailureHandler authFailureHandler; - private SamlUserReplicator samlUserReplicator; - private SamlServerConfiguration serviceProviderConfiguration; + private final SamlAuthSuccessHandler samlSuccessHandler; + private final AuthFailureHandler authFailureHandler; + private final SamlUserReplicator samlUserReplicator; + private final SamlServerConfiguration serviceProviderConfiguration; public SamlServiceProviderBeanConfiguration( @Value("${rp.auth.saml.session-live}") Integer maxSessionLive, diff --git a/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderConfiguration.java b/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderConfiguration.java index 188116d5..003cb61f 100644 --- a/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderConfiguration.java +++ b/src/main/java/com/epam/reportportal/auth/config/saml/SamlServiceProviderConfiguration.java @@ -20,14 +20,14 @@ import static java.util.Base64.getEncoder; import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.converter.SamlConverter; import com.epam.reportportal.auth.util.CertificationUtil; import com.epam.reportportal.auth.util.RequestUtil; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; import com.google.common.collect.Lists; import java.security.PrivateKey; import java.security.cert.CertificateEncodingException; @@ -101,9 +101,9 @@ public class SamlServiceProviderConfiguration { @Autowired private Provider requestProvider; - private IntegrationTypeRepository integrationTypeRepository; + private final IntegrationTypeRepository integrationTypeRepository; - private IntegrationRepository integrationRepository; + private final IntegrationRepository integrationRepository; public SamlServiceProviderConfiguration(IntegrationTypeRepository integrationTypeRepository, IntegrationRepository integrationRepository) { diff --git a/src/main/java/com/epam/reportportal/auth/dao/AttributeRepository.java b/src/main/java/com/epam/reportportal/auth/dao/AttributeRepository.java new file mode 100644 index 00000000..177bbd1e --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/AttributeRepository.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + + +import com.epam.reportportal.auth.entity.attribute.Attribute; +import java.util.Collection; +import java.util.Set; + +/** + * @author Andrey Plisunov + */ +public interface AttributeRepository extends ReportPortalRepository { + + Set findAllByNameIn(Collection names); + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/IntegrationRepository.java b/src/main/java/com/epam/reportportal/auth/dao/IntegrationRepository.java new file mode 100644 index 00000000..58e5f958 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/IntegrationRepository.java @@ -0,0 +1,59 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +/** + * @author Ivan Budayeu + * @author Andrei Varabyeu + */ +@Repository +public interface IntegrationRepository extends ReportPortalRepository { + + /** + * @param name {@link Integration#getName()} + * @param integrationTypeId {@link Integration#getType()}#{@link IntegrationType#getId()} + * @return {@link Optional} with {@link Integration} + */ + Optional findByNameAndTypeIdAndProjectIdIsNull(String name, Long integrationTypeId); + + /** + * @param id {@link Integration#getId()} ()} + * @param integrationTypeId {@link Integration#getType()}#{@link IntegrationType#getId()} + * @return {@link Optional} with {@link Integration} + */ + Optional findByIdAndTypeIdAndProjectIdIsNull(Long id, Long integrationTypeId); + + /** + * Retrieve all {@link Integration} with {@link Integration#project} == null by integration type + * + * @param integrationType {@link Integration#type} + * @return @return The {@link List} of the {@link Integration} + */ + @Query(value = "SELECT i FROM Integration i WHERE i.project IS NULL AND i.type = :integrationType order by i.creationDate desc") + List findAllGlobalByType(@Param("integrationType") IntegrationType integrationType); + + + @Query(value = "SELECT * FROM integration i LEFT OUTER JOIN integration_type it ON i.type = it.id WHERE it.name IN (:types) order by i.creation_date desc", nativeQuery = true) + List findAllByTypeIn(@Param("types") String... types); +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/IntegrationTypeRepository.java b/src/main/java/com/epam/reportportal/auth/dao/IntegrationTypeRepository.java new file mode 100644 index 00000000..be0054cc --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/IntegrationTypeRepository.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import com.epam.reportportal.auth.entity.integration.IntegrationType; +import java.util.Optional; + +/** + * Repository for {@link IntegrationType} entity + * + * @author Yauheni_Martynau + */ +public interface IntegrationTypeRepository extends ReportPortalRepository { + + /** + * Find integration by name + * + * @param name Integration name + * @return @return The {@link Optional} of the {@link IntegrationType} + */ + Optional findByName(String name); + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/IssueTypeRepository.java b/src/main/java/com/epam/reportportal/auth/dao/IssueTypeRepository.java new file mode 100644 index 00000000..a5aa2a63 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/IssueTypeRepository.java @@ -0,0 +1,32 @@ +/* + * Copyright 2024 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + + +import com.epam.reportportal.auth.entity.item.issue.IssueType; +import java.util.List; +import org.springframework.data.jpa.repository.Query; + +/** + * @author Siarhei Hrabko + */ +public interface IssueTypeRepository extends ReportPortalRepository { + + @Query(value = "SELECT from issue_type it join public.issue_group ig on it.issue_group_id = ig.issue_group_id where it.locator in (:TestItemIssueGroup.values())", nativeQuery = true) + List getDefaultIssueTypes(); + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/OAuthRegistrationRepository.java b/src/main/java/com/epam/reportportal/auth/dao/OAuthRegistrationRepository.java new file mode 100644 index 00000000..ece5fcdc --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/OAuthRegistrationRepository.java @@ -0,0 +1,24 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; + +public interface OAuthRegistrationRepository extends + ReportPortalRepository { + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/ProjectRepository.java b/src/main/java/com/epam/reportportal/auth/dao/ProjectRepository.java new file mode 100644 index 00000000..155adac4 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/ProjectRepository.java @@ -0,0 +1,29 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import com.epam.reportportal.auth.entity.project.Project; +import java.util.Optional; + +public interface ProjectRepository extends ReportPortalRepository { + + Optional findByName(String name); + + boolean existsByName(String name); + + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/ReportPortalRepository.java b/src/main/java/com/epam/reportportal/auth/dao/ReportPortalRepository.java new file mode 100644 index 00000000..6fa57718 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/ReportPortalRepository.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import java.io.Serializable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; + +/** + * @author Pavel Bortnik + */ +@NoRepositoryBean +public interface ReportPortalRepository extends JpaRepository { + + void refresh(T t); + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/ReportPortalRepositoryImpl.java b/src/main/java/com/epam/reportportal/auth/dao/ReportPortalRepositoryImpl.java new file mode 100644 index 00000000..449aaa76 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/ReportPortalRepositoryImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import java.io.Serializable; +import javax.persistence.EntityManager; +import org.springframework.data.jpa.repository.support.JpaEntityInformation; +import org.springframework.data.jpa.repository.support.SimpleJpaRepository; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author Pavel Bortnik + */ +public class ReportPortalRepositoryImpl extends + SimpleJpaRepository + implements ReportPortalRepository { + + private final EntityManager entityManager; + + + public ReportPortalRepositoryImpl(JpaEntityInformation entityInformation, + EntityManager entityManager) { + super(entityInformation, entityManager); + this.entityManager = entityManager; + } + + + @Override + @Transactional + public void refresh(T t) { + entityManager.refresh(t); + } + + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/ServerSettingsRepository.java b/src/main/java/com/epam/reportportal/auth/dao/ServerSettingsRepository.java new file mode 100644 index 00000000..45d30f9b --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/ServerSettingsRepository.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import com.epam.reportportal.auth.entity.ServerSettings; +import java.util.Optional; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; + +/** + * @author Ivan Budaev + */ +public interface ServerSettingsRepository extends ReportPortalRepository { + + @Modifying + @Query(value = "INSERT INTO server_settings (key, value) VALUES ('secret.key', gen_random_bytes(32)) RETURNING value", nativeQuery = true) + String generateSecret(); + + Optional findByKey(String key); +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/UserRepository.java b/src/main/java/com/epam/reportportal/auth/dao/UserRepository.java new file mode 100644 index 00000000..4ac12a2c --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/UserRepository.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.dao; + +import com.epam.reportportal.auth.entity.user.User; +import java.util.Optional; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +/** + * @author Ivan Budayeu + */ +public interface UserRepository extends ReportPortalRepository { + + Optional findByEmail(String email); + + /** + * @param login user login for search + * @return {@link Optional} of {@link User} + */ + Optional findByLogin(String login); + + /** + * Updates user's last login value + * + * @param username User + */ + @Modifying(clearAutomatically = true) + @Query(value = "UPDATE users SET metadata = jsonb_set(metadata, '{metadata,last_login}', to_jsonb(round(extract(EPOCH from clock_timestamp()) * 1000)), TRUE ) WHERE login = :username", nativeQuery = true) + void updateLastLoginDate(@Param("username") String username); + +} diff --git a/src/main/java/com/epam/reportportal/auth/dao/converters/JpaInstantConverter.java b/src/main/java/com/epam/reportportal/auth/dao/converters/JpaInstantConverter.java new file mode 100644 index 00000000..42a1873e --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/dao/converters/JpaInstantConverter.java @@ -0,0 +1,26 @@ +package com.epam.reportportal.auth.dao.converters; + +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import org.springframework.lang.Nullable; + +@Converter(autoApply = true) +public class JpaInstantConverter implements AttributeConverter { + + @Nullable + @Override + public Timestamp convertToDatabaseColumn(Instant instant) { + return instant == null ? null + : Timestamp.valueOf(LocalDateTime.ofInstant(instant, ZoneOffset.UTC)); + } + + @Nullable + @Override + public Instant convertToEntityAttribute(Timestamp timestamp) { + return timestamp == null ? null : timestamp.toInstant(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/endpoint/AuthConfigurationEndpoint.java b/src/main/java/com/epam/reportportal/auth/endpoint/AuthConfigurationEndpoint.java index 55116eae..9191560c 100644 --- a/src/main/java/com/epam/reportportal/auth/endpoint/AuthConfigurationEndpoint.java +++ b/src/main/java/com/epam/reportportal/auth/endpoint/AuthConfigurationEndpoint.java @@ -16,16 +16,16 @@ package com.epam.reportportal.auth.endpoint; +import com.epam.reportportal.auth.OperationCompletionRS; +import com.epam.reportportal.auth.commons.ReportPortalUser; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.handler.CreateAuthIntegrationHandler; import com.epam.reportportal.auth.integration.handler.DeleteAuthIntegrationHandler; import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationHandler; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.auth.OperationCompletionRS; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.beans.PropertyEditorSupport; @@ -69,10 +69,10 @@ public AuthConfigurationEndpoint(CreateAuthIntegrationHandler createAuthIntegrat /** * Creates or updates auth integration settings. * - * @param request Update request + * @param request Update request * @param authType Type of Auth - * @param user User - * @return Successful message or an error + * @param user User + * @return Successful message or an error */ @Transactional @PostMapping(value = "/{authType}") @@ -87,9 +87,9 @@ public AbstractAuthResource createAuthIntegration(@RequestBody @Valid UpdateAuth /** * Creates or updates auth integration settings * - * @param request Update request - * @param authType Type of Auth - * @param user User + * @param request Update request + * @param authType Type of Auth + * @param user User * @param integrationId Integration ID * @return Successful message or an error */ diff --git a/src/main/java/com/epam/reportportal/auth/endpoint/AuthProvidersInfoContributor.java b/src/main/java/com/epam/reportportal/auth/endpoint/AuthProvidersInfoContributor.java index 23db8203..529cb853 100644 --- a/src/main/java/com/epam/reportportal/auth/endpoint/AuthProvidersInfoContributor.java +++ b/src/main/java/com/epam/reportportal/auth/endpoint/AuthProvidersInfoContributor.java @@ -20,15 +20,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.springframework.web.servlet.support.ServletUriComponentsBuilder.fromCurrentContextPath; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.dao.OAuthRegistrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.parameter.SamlParameter; import com.epam.reportportal.auth.oauth.OAuthProvider; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.dao.OAuthRegistrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; import com.google.common.collect.Maps; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/epam/reportportal/auth/endpoint/MetadataContributor.java b/src/main/java/com/epam/reportportal/auth/endpoint/MetadataContributor.java index 4e11c437..f41ec036 100644 --- a/src/main/java/com/epam/reportportal/auth/endpoint/MetadataContributor.java +++ b/src/main/java/com/epam/reportportal/auth/endpoint/MetadataContributor.java @@ -17,7 +17,7 @@ package com.epam.reportportal.auth.endpoint; -import com.epam.ta.reportportal.entity.project.ProjectRole; +import com.epam.reportportal.auth.entity.project.ProjectRole; import com.google.common.collect.ImmutableMap; import java.util.Arrays; import org.springframework.boot.actuate.info.Info; diff --git a/src/main/java/com/epam/reportportal/auth/endpoint/OAuthConfigurationEndpoint.java b/src/main/java/com/epam/reportportal/auth/endpoint/OAuthConfigurationEndpoint.java index c5463b80..d0f3fe61 100644 --- a/src/main/java/com/epam/reportportal/auth/endpoint/OAuthConfigurationEndpoint.java +++ b/src/main/java/com/epam/reportportal/auth/endpoint/OAuthConfigurationEndpoint.java @@ -20,11 +20,11 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST; import static org.springframework.web.bind.annotation.RequestMethod.PUT; +import com.epam.reportportal.auth.OperationCompletionRS; import com.epam.reportportal.auth.integration.handler.CreateAuthIntegrationHandler; import com.epam.reportportal.auth.integration.handler.DeleteAuthIntegrationHandler; import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationHandler; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; -import com.epam.reportportal.auth.OperationCompletionRS; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.Map; @@ -71,7 +71,7 @@ public OAuthConfigurationEndpoint(CreateAuthIntegrationHandler createAuthIntegra * Updates oauth integration settings * * @param clientRegistrationResource OAuth configuration - * @param oauthProviderId Oauth settings Profile Id + * @param oauthProviderId Oauth settings Profile Id * @return All defined OAuth integration settings */ @Transactional diff --git a/src/main/java/com/epam/reportportal/auth/endpoint/SsoEndpoint.java b/src/main/java/com/epam/reportportal/auth/endpoint/SsoEndpoint.java index 3c179210..664d678f 100644 --- a/src/main/java/com/epam/reportportal/auth/endpoint/SsoEndpoint.java +++ b/src/main/java/com/epam/reportportal/auth/endpoint/SsoEndpoint.java @@ -19,7 +19,7 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; -import com.epam.ta.reportportal.commons.ReportPortalUser; +import com.epam.reportportal.auth.commons.ReportPortalUser; import com.google.common.collect.ImmutableMap; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/src/main/java/com/epam/reportportal/auth/entity/AnalyzeMode.java b/src/main/java/com/epam/reportportal/auth/entity/AnalyzeMode.java new file mode 100644 index 00000000..6b96a64b --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/AnalyzeMode.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity; + +import java.util.Arrays; +import java.util.Optional; +import lombok.Getter; + +/** + * @author Pavel Bortnik + */ +@Getter +public enum AnalyzeMode { + + ALL_LAUNCHES("ALL"), + BY_LAUNCH_NAME("LAUNCH_NAME"), + CURRENT_LAUNCH("CURRENT_LAUNCH"), + PREVIOUS_LAUNCH("PREVIOUS_LAUNCH"), + CURRENT_AND_THE_SAME_NAME("CURRENT_AND_THE_SAME_NAME"); + + private String value; + + AnalyzeMode(String value) { + this.value = value; + } + + public static Optional fromString(String mode) { + return Arrays.stream(AnalyzeMode.values()).filter(it -> it.getValue().equalsIgnoreCase(mode)) + .findFirst(); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/Metadata.java b/src/main/java/com/epam/reportportal/auth/entity/Metadata.java new file mode 100644 index 00000000..406c1d16 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/Metadata.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity; + +import com.epam.reportportal.auth.commons.JsonbUserType; +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Pavel Bortnik + */ +@Setter +@Getter +public class Metadata extends JsonbUserType implements Serializable { + + private Map metadata; + + public Metadata() { + } + + public Metadata(Map metadata) { + this.metadata = metadata; + } + + @Override + public Class returnedClass() { + return Metadata.class; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Metadata comparing = (Metadata) o; + return Objects.equals(metadata, comparing.metadata); + } + + @Override + public int hashCode() { + return Objects.hash(metadata); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/ServerSettings.java b/src/main/java/com/epam/reportportal/auth/entity/ServerSettings.java new file mode 100644 index 00000000..2bf50744 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/ServerSettings.java @@ -0,0 +1,92 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity; + +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "server_settings", schema = "public") +public class ServerSettings implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false, precision = 64) + private Long id; + + @Column(name = "key", unique = true, nullable = false) + private String key; + + @Column(name = "value") + private String value; + + public ServerSettings() { + } + + public ServerSettings(String key, String value) { + this.key = key; + this.value = value; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ServerSettings that = (ServerSettings) o; + return Objects.equals(id, that.id) && Objects.equals(key, that.key) && Objects.equals(value, + that.value); + } + + @Override + public int hashCode() { + return Objects.hash(id, key, value); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/Activity.java b/src/main/java/com/epam/reportportal/auth/entity/activity/Activity.java new file mode 100644 index 00000000..03e569a6 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/Activity.java @@ -0,0 +1,130 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import com.epam.reportportal.auth.dao.converters.JpaInstantConverter; +import java.io.Serializable; +import java.time.Instant; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; + +/** + * Activity table entity + * + * @author Ryhor Kukharenka + */ +@Entity +@Table(name = "activity", schema = "public") +@TypeDef(name = "activityDetails", typeClass = ActivityDetails.class) +@Getter +@Setter +@ToString +public class Activity implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false, precision = 64) + private Long id; + + @Column(name = "created_at", nullable = false) + @Convert(converter = JpaInstantConverter.class) + private Instant createdAt; + + @Column(name = "action", nullable = false) + @Enumerated(EnumType.STRING) + private EventAction action; + + @Column(name = "event_name", nullable = false) + private String eventName; + + @Column(name = "priority", nullable = false) + @Enumerated(EnumType.STRING) + private EventPriority priority; + + @Column(name = "object_id") + private Long objectId; + + @Column(name = "object_name", nullable = false) + private String objectName; + + @Enumerated(EnumType.STRING) + @Column(name = "object_type", nullable = false) + private EventObject objectType; + + @Column(name = "project_id") + private Long projectId; + + @Transient + private String projectName; + + @Column(name = "details") + @Type(type = "activityDetails") + private ActivityDetails details; + + @Column(name = "subject_id", precision = 32) + private Long subjectId; + + @Column(name = "subject_name", nullable = false) + private String subjectName; + + @Enumerated(EnumType.STRING) + @Column(name = "subject_type", nullable = false) + private EventSubject subjectType; + + /** + * A boolean to decide whether to save the event. + */ + @Transient + private boolean isSavedEvent; + + public Activity() { + this.isSavedEvent = true; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Activity activity = (Activity) o; + return Objects.equals(id, activity.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/ActivityAction.java b/src/main/java/com/epam/reportportal/auth/entity/activity/ActivityAction.java new file mode 100644 index 00000000..1aa21142 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/ActivityAction.java @@ -0,0 +1,44 @@ +/* + * Copyright 2023 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import java.util.Arrays; +import java.util.Optional; +import lombok.Getter; + +/** + * @author Ihar Kahadouski + */ +@Getter +public enum ActivityAction { + + CREATE_USER("createUser"), + ASSIGN_USER("assignUser"), + CREATE_PROJECT("createProject"); + + private final String value; + + ActivityAction(String value) { + this.value = value; + } + + public static Optional fromString(String string) { + return Optional.ofNullable(string).flatMap( + str -> Arrays.stream(values()).filter(it -> it.value.equalsIgnoreCase(str)).findAny()); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/ActivityDetails.java b/src/main/java/com/epam/reportportal/auth/entity/activity/ActivityDetails.java new file mode 100644 index 00000000..67c5f5ce --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/ActivityDetails.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import com.epam.reportportal.auth.commons.JsonbUserType; +import com.google.common.collect.Lists; +import java.io.Serializable; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ihar Kahadouski + */ +@Setter +@Getter +public class ActivityDetails extends JsonbUserType implements Serializable { + + private List history = Lists.newArrayList(); + + public ActivityDetails() { + } + + public ActivityDetails(List history) { + this.history = history; + } + + @Override + public Class returnedClass() { + return ActivityDetails.class; + } + + public void addHistoryField(HistoryField historyField) { + history.add(historyField); + } + + @Override + public String toString() { + return "ActivityDetails{" + "history=" + history + '}'; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/EventAction.java b/src/main/java/com/epam/reportportal/auth/entity/activity/EventAction.java new file mode 100644 index 00000000..face3d25 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/EventAction.java @@ -0,0 +1,41 @@ +/* + * Copyright 2023 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import java.util.Arrays; +import java.util.Optional; +import lombok.Getter; + +@Getter +public enum EventAction { + CREATE("create"), + ASSIGN("assign"); + + private final String value; + + EventAction(String value) { + this.value = value; + } + + public static Optional fromString(String string) { + return Optional.ofNullable(string) + .flatMap(str -> Arrays.stream(values()) + .filter(it -> it.value.equalsIgnoreCase(str)) + .findAny()); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/EventObject.java b/src/main/java/com/epam/reportportal/auth/entity/activity/EventObject.java new file mode 100644 index 00000000..4158bd69 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/EventObject.java @@ -0,0 +1,33 @@ +/* + * Copyright 2023 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import lombok.Getter; + +@Getter +public enum EventObject { + + PROJECT("project"), + USER("user"); + + private final String value; + + EventObject(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/EventPriority.java b/src/main/java/com/epam/reportportal/auth/entity/activity/EventPriority.java new file mode 100644 index 00000000..c886a106 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/EventPriority.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import lombok.Getter; + +@Getter +public enum EventPriority { + + CRITICAL("critical"), + HIGH("high"), + MEDIUM("medium"), + LOW("low"), + INFO("info"); + + private final String value; + + EventPriority(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/EventSubject.java b/src/main/java/com/epam/reportportal/auth/entity/activity/EventSubject.java new file mode 100644 index 00000000..5028a9fd --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/EventSubject.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import lombok.Getter; + +@Getter +public enum EventSubject { + USER("user"), + APPLICATION("application"), + RULE("rule"), + CUSTOM("custom"); + + private final String value; + + EventSubject(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/activity/HistoryField.java b/src/main/java/com/epam/reportportal/auth/entity/activity/HistoryField.java new file mode 100644 index 00000000..092eecc0 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/activity/HistoryField.java @@ -0,0 +1,79 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.activity; + +import com.epam.reportportal.auth.commons.JsonbUserType; +import java.io.Serializable; +import java.util.Objects; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ihar Kahadouski + */ +@Setter +@Getter +public class HistoryField extends JsonbUserType implements Serializable { + + private String field; + private String oldValue; + private String newValue; + + public HistoryField() { + } + + public HistoryField(String field, String oldValue, String newValue) { + this.field = field; + this.oldValue = oldValue; + this.newValue = newValue; + } + + public static HistoryField of(String field, String oldValue, String newValue) { + return new HistoryField(field, oldValue, newValue); + } + + @Override + public Class returnedClass() { + return HistoryField.class; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HistoryField that = (HistoryField) o; + return Objects.equals(field, that.field) && Objects.equals(oldValue, that.oldValue) + && Objects.equals(newValue, that.newValue); + } + + @Override + public int hashCode() { + return Objects.hash(field, oldValue, newValue); + } + + @Override + public String toString() { + return "HistoryField{" + "field='" + field + '\'' + + ", oldValue='" + oldValue + '\'' + + ", newValue='" + newValue + '\'' + + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/attachment/Attachment.java b/src/main/java/com/epam/reportportal/auth/entity/attachment/Attachment.java new file mode 100644 index 00000000..44cf2db8 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/attachment/Attachment.java @@ -0,0 +1,97 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.attachment; + +import com.epam.reportportal.auth.dao.converters.JpaInstantConverter; +import java.io.Serializable; +import java.time.Instant; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ivan Budayeu + */ +@Setter +@Getter +@Entity +@Table(name = "attachment") +public class Attachment implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "file_name") + private String fileName; + + @Column(name = "file_id") + private String fileId; + + @Column(name = "thumbnail_id") + private String thumbnailId; + + @Column(name = "content_type") + private String contentType; + + @Column(name = "file_size") + private long fileSize; + + @Column(name = "creation_date") + @Convert(converter = JpaInstantConverter.class) + private Instant creationDate; + + @Column(name = "project_id") + private Long projectId; + + @Column(name = "launch_id") + private Long launchId; + + @Column(name = "item_id") + private Long itemId; + + public Attachment() { + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Attachment that = (Attachment) o; + return Objects.equals(fileId, that.fileId) && Objects.equals(thumbnailId, that.thumbnailId) + && Objects.equals(contentType, + that.contentType + ) && Objects.equals(fileSize, that.fileSize) && Objects.equals(creationDate, that.creationDate) + && Objects.equals(fileName, that.fileName); + } + + @Override + public int hashCode() { + return Objects.hash(fileId, thumbnailId, contentType, fileSize, creationDate, fileName); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/attachment/BinaryData.java b/src/main/java/com/epam/reportportal/auth/entity/attachment/BinaryData.java new file mode 100644 index 00000000..7d49818f --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/attachment/BinaryData.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.attachment; + +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import java.io.IOException; +import java.io.InputStream; +import lombok.Getter; +import org.springframework.web.multipart.MultipartFile; + +/** + * Binary data representation. Contains only input stream and data type. Introduced to simplify + * store/retrieve operations + * + * @author Andrei Varabyeu + */ +@Getter +public class BinaryData { + + private String fileName; + + /** + * MIME Type of Binary Data + */ + private final String contentType; + + /** + * Data Stream + */ + private final InputStream inputStream; + + /** + * Content length + */ + private final Long length; + + public BinaryData(String contentType, Long length, InputStream inputStream) { + this.contentType = contentType; + this.inputStream = inputStream; + this.length = length; + } + + public BinaryData(String fileName, String contentType, Long length, InputStream inputStream) { + this.fileName = fileName; + this.contentType = contentType; + this.length = length; + this.inputStream = inputStream; + } + + public BinaryData(MultipartFile multipartFile) { + this.contentType = multipartFile.getContentType(); + this.length = multipartFile.getSize(); + + try { + this.inputStream = multipartFile.getInputStream(); + } catch (IOException e) { + throw new ReportPortalException(ErrorType.INCORRECT_REQUEST, + "Unable to create binary data from multipart file"); + } + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/attribute/Attribute.java b/src/main/java/com/epam/reportportal/auth/entity/attribute/Attribute.java new file mode 100644 index 00000000..07e73d8c --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/attribute/Attribute.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.attribute; + +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Andrey Plisunov + */ +@Setter +@Getter +@Entity +@Table(name = "attribute") +public class Attribute implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name") + private String name; + + public Attribute() { + } + + public Attribute(Long id, String name) { + this.id = id; + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Attribute attribute = (Attribute) o; + return Objects.equals(name, attribute.name); + } + + @Override + public int hashCode() { + + return Objects.hash(name); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/FeatureFlag.java b/src/main/java/com/epam/reportportal/auth/entity/enums/FeatureFlag.java new file mode 100644 index 00000000..92be2909 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/FeatureFlag.java @@ -0,0 +1,34 @@ +package com.epam.reportportal.auth.entity.enums; + +import java.util.Arrays; +import java.util.Optional; +import lombok.Getter; + +/** + * Enumeration of current feature flags. + * + * @author Ivan Kustau + */ +@Getter +public enum FeatureFlag { + SINGLE_BUCKET("singleBucket"), + DEFAULT_LDAP_ENCODER("defaultLdapEncoder"); + + private final String name; + + FeatureFlag(String name) { + this.name = name; + } + + /** + * Returns {@link Optional} of {@link FeatureFlag} by string. + * + * @param name Name of feature flag + * @return {@link Optional} of {@link FeatureFlag} by string + */ + public static Optional fromString(String name) { + return Optional.ofNullable(name).flatMap( + str -> Arrays.stream(values()).filter(it -> it.name.equalsIgnoreCase(str)).findAny()); + + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/IntegrationAuthFlowEnum.java b/src/main/java/com/epam/reportportal/auth/entity/enums/IntegrationAuthFlowEnum.java new file mode 100644 index 00000000..4b4701be --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/IntegrationAuthFlowEnum.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.enums; + +import java.util.Arrays; +import java.util.Optional; + +public enum IntegrationAuthFlowEnum { + + OAUTH, + BASIC, + TOKEN, + FORM, + LDAP; + + public static Optional findByName(String name) { + return Arrays.stream(IntegrationAuthFlowEnum.values()) + .filter(i -> i.name().equalsIgnoreCase(name)).findAny(); + } + + public static boolean isPresent(String name) { + return findByName(name).isPresent(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/IntegrationGroupEnum.java b/src/main/java/com/epam/reportportal/auth/entity/enums/IntegrationGroupEnum.java new file mode 100644 index 00000000..6c9e3c81 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/IntegrationGroupEnum.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.enums; + +import java.util.Arrays; +import java.util.Optional; + +public enum IntegrationGroupEnum { + + BTS, + NOTIFICATION, + AUTH, + OTHER, + IMPORT; + + public static Optional findByName(String name) { + return Arrays.stream(IntegrationGroupEnum.values()).filter(i -> i.name().equalsIgnoreCase(name)) + .findAny(); + } + + public static boolean isPresent(String name) { + return findByName(name).isPresent(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/PostgreSQLEnumType.java b/src/main/java/com/epam/reportportal/auth/entity/enums/PostgreSQLEnumType.java new file mode 100644 index 00000000..0f02e260 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/PostgreSQLEnumType.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.enums; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Types; +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.EnumType; + +/** + * @author Pavel Bortnik + */ +public class PostgreSQLEnumType extends EnumType { + + public void nullSafeSet(PreparedStatement st, Object value, int index, + SharedSessionContractImplementor session) + throws HibernateException, SQLException { + if (value == null) { + st.setNull(index, Types.OTHER); + } else { + st.setObject(index, value.toString(), Types.OTHER); + } + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/ProjectAttributeEnum.java b/src/main/java/com/epam/reportportal/auth/entity/enums/ProjectAttributeEnum.java new file mode 100644 index 00000000..f0691ac4 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/ProjectAttributeEnum.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.enums; + +import com.epam.reportportal.auth.entity.AnalyzeMode; +import com.epam.reportportal.auth.entity.project.ProjectAnalyzerConfig; +import java.time.Duration; +import java.util.Arrays; +import java.util.Optional; +import lombok.Getter; + +/** + * Enum with a list of basic required project parameters. + * + * @author Andrey Plisunov + */ +@Getter +public enum ProjectAttributeEnum { + + NOTIFICATIONS_ENABLED("notifications.enabled", String.valueOf(true)), + NOTIFICATIONS_EMAIL_ENABLED("notifications.email.enabled", String.valueOf(true)), + + INTERRUPT_JOB_TIME(Prefix.JOB + "interruptJobTime", + String.valueOf(Duration.ofDays(1).toSeconds())), + KEEP_LAUNCHES(Prefix.JOB + "keepLaunches", String.valueOf(Duration.ofDays(90).toSeconds())), + KEEP_LOGS(Prefix.JOB + "keepLogs", String.valueOf(Duration.ofDays(90).toSeconds())), + KEEP_SCREENSHOTS(Prefix.JOB + "keepScreenshots", String.valueOf(Duration.ofDays(14).toSeconds())), + + MIN_SHOULD_MATCH(Prefix.ANALYZER + "minShouldMatch", + String.valueOf(ProjectAnalyzerConfig.MIN_SHOULD_MATCH)), + NUMBER_OF_LOG_LINES(Prefix.ANALYZER + "numberOfLogLines", + String.valueOf(ProjectAnalyzerConfig.NUMBER_OF_LOG_LINES)), + INDEXING_RUNNING(Prefix.ANALYZER + "indexingRunning", String.valueOf(false)), + AUTO_PATTERN_ANALYZER_ENABLED(Prefix.ANALYZER + "isAutoPatternAnalyzerEnabled", + String.valueOf(false)), + AUTO_ANALYZER_ENABLED(Prefix.ANALYZER + "isAutoAnalyzerEnabled", String.valueOf(true)), + AUTO_ANALYZER_MODE(Prefix.ANALYZER + "autoAnalyzerMode", + AnalyzeMode.CURRENT_AND_THE_SAME_NAME.getValue()), + ALL_MESSAGES_SHOULD_MATCH(Prefix.ANALYZER + "allMessagesShouldMatch", String.valueOf(false)), + SEARCH_LOGS_MIN_SHOULD_MATCH(Prefix.ANALYZER + "searchLogsMinShouldMatch", + String.valueOf(ProjectAnalyzerConfig.MIN_SHOULD_MATCH)), + AUTO_UNIQUE_ERROR_ANALYZER_ENABLED(Prefix.ANALYZER + Prefix.UNIQUE_ERROR + "enabled", + String.valueOf(true)), + UNIQUE_ERROR_ANALYZER_REMOVE_NUMBERS(Prefix.ANALYZER + Prefix.UNIQUE_ERROR + "removeNumbers", + String.valueOf(true)); + + public static final String FOREVER_ALIAS = "0"; + private String attribute; + private String defaultValue; + + ProjectAttributeEnum(String attribute, String defaultValue) { + this.attribute = attribute; + this.defaultValue = defaultValue; + } + + public static Optional findByAttributeName(String attributeName) { + return Arrays.stream(ProjectAttributeEnum.values()) + .filter(v -> v.getAttribute().equalsIgnoreCase(attributeName)).findAny(); + } + + public static boolean isPresent(String name) { + return findByAttributeName(name).isPresent(); + } + + public static class Prefix { + + private Prefix() { + } + + public static final String ANALYZER = "analyzer."; + public static final String JOB = "job."; + public static final String UNIQUE_ERROR = "uniqueError."; + } +} + + diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/ProjectType.java b/src/main/java/com/epam/reportportal/auth/entity/enums/ProjectType.java new file mode 100644 index 00000000..56cb5209 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/ProjectType.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.enums; + +import java.util.Arrays; +import java.util.Optional; + +/** + * Project Type enumeration
Used for supporting different project types processing + * + * @author Andrei_Ramanchuk + * @author Andrei Varabyeu + */ +public enum ProjectType { + + PERSONAL, + INTERNAL, + UPSA; + + public static Optional findByName(String name) { + return Arrays.stream(ProjectType.values()).filter(type -> type.name().equalsIgnoreCase(name)) + .findAny(); + } + + public static boolean isPresent(String name) { + return findByName(name).isPresent(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/enums/TestItemIssueGroup.java b/src/main/java/com/epam/reportportal/auth/entity/enums/TestItemIssueGroup.java new file mode 100644 index 00000000..f706f297 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/enums/TestItemIssueGroup.java @@ -0,0 +1,79 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.enums; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import lombok.Getter; + +/** + * Vocabulary for supported test item issues types. They are applied as markers for test steps. User + * marks test step according to the type of the issue, caused it's failure.
locator - predefined + * ID for immutable issue type
+ * + * @author Dzianis Shlychkou + * @author Andrei_Ramanchuk + */ +@Getter +public enum TestItemIssueGroup /*implements StatisticsAwareness*/ { + + NOT_ISSUE_FLAG("NOT_ISSUE", "notIssue", ""), + + PRODUCT_BUG("PRODUCT_BUG", "productBug", "pb001"), + AUTOMATION_BUG("AUTOMATION_BUG", "automationBug", "ab001"), + SYSTEM_ISSUE("SYSTEM_ISSUE", "systemIssue", "si001"), + TO_INVESTIGATE("TO_INVESTIGATE", "toInvestigate", "ti001"), + NO_DEFECT("NO_DEFECT", "noDefect", "nd001"); + + private final String value; + + private final String issueCounterField; + + private final String locator; + + TestItemIssueGroup(String value, String executionCounterField, String locator) { + this.value = value; + this.issueCounterField = executionCounterField; + this.locator = locator; + } + + /** + * Retrieves TestItemIssueType value by it's string value + * + * @param value - string representation of desired TestItemIssueType value + * @return TestItemIssueType value + */ + public static Optional fromValue(String value) { + return Arrays.stream(TestItemIssueGroup.values()) + .filter(type -> type.getValue().equalsIgnoreCase(value)).findAny(); + } + + public static TestItemIssueGroup validate(String value) { + return Arrays.stream(TestItemIssueGroup.values()) + .filter(type -> type.getValue().replace(" ", "_").equalsIgnoreCase(value)) + .findAny() + .orElse(null); + } + + public static List validValues() { + return Arrays.stream(TestItemIssueGroup.values()).map(TestItemIssueGroup::getValue) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/integration/Integration.java b/src/main/java/com/epam/reportportal/auth/entity/integration/Integration.java new file mode 100644 index 00000000..9af8ab40 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/integration/Integration.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.integration; + +import com.epam.reportportal.auth.dao.converters.JpaInstantConverter; +import com.epam.reportportal.auth.entity.project.Project; +import java.io.Serializable; +import java.time.Instant; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +/** + * @author Yauheni_Martynau + */ +@Setter +@Getter +@Entity +@EntityListeners(AuditingEntityListener.class) +@TypeDef(name = "params", typeClass = IntegrationParams.class) +@Table(name = "integration", schema = "public") +@Inheritance(strategy = InheritanceType.JOINED) +public class Integration implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "name") + private String name; + + @ManyToOne + @JoinColumn(name = "project_id") + private Project project; + + @ManyToOne + @JoinColumn(name = "type") + private IntegrationType type; + + @Type(type = "params") + @Column(name = "params") + private IntegrationParams params; + + @Column(name = "enabled") + private boolean enabled; + + @Column(name = "creator") + private String creator; + + @CreatedDate + @Column(name = "creation_date") + @Convert(converter = JpaInstantConverter.class) + private Instant creationDate; + + public Integration(Long id, Project project, IntegrationType type, IntegrationParams params, + Instant creationDate) { + this.id = id; + this.project = project; + this.type = type; + this.params = params; + this.creationDate = creationDate; + } + + public Integration() { + } + +} + diff --git a/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationParams.java b/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationParams.java new file mode 100644 index 00000000..b33867ab --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationParams.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.integration; + +import com.epam.reportportal.auth.commons.JsonbUserType; +import java.io.Serializable; +import java.util.Map; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * @author Yauheni_Martynau + */ +@Setter +@Getter +@NoArgsConstructor +public class IntegrationParams extends JsonbUserType implements Serializable { + + private Map params; + + public IntegrationParams(Map params) { + this.params = params; + } + + @Override + public Class returnedClass() { + return IntegrationParams.class; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationType.java b/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationType.java new file mode 100644 index 00000000..3547b002 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationType.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.integration; + +import com.epam.reportportal.auth.dao.converters.JpaInstantConverter; +import com.epam.reportportal.auth.entity.enums.IntegrationAuthFlowEnum; +import com.epam.reportportal.auth.entity.enums.IntegrationGroupEnum; +import com.epam.reportportal.auth.entity.enums.PostgreSQLEnumType; +import com.google.common.collect.Sets; +import java.io.Serializable; +import java.time.Instant; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.springframework.data.annotation.CreatedDate; + +/** + * @author Yauheni_Martynau + */ +@Setter +@Getter +@Entity +@TypeDef(name = "details", typeClass = IntegrationTypeDetails.class) +@TypeDef(name = "pgsql_enum", typeClass = PostgreSQLEnumType.class) +@Table(name = "integration_type", schema = "public") +public class IntegrationType implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false, precision = 64) + private Long id; + + @Column(name = "name", nullable = false) + private String name; + + @Enumerated(EnumType.STRING) + @Type(type = "pqsql_enum") + @Column(name = "auth_flow") + private IntegrationAuthFlowEnum authFlow; + + @CreatedDate + @Column(name = "creation_date", nullable = false) + @Convert(converter = JpaInstantConverter.class) + private Instant creationDate; + + @Enumerated(EnumType.STRING) + @Type(type = "pqsql_enum") + @Column(name = "group_type", nullable = false) + private IntegrationGroupEnum integrationGroup; + + @Column(name = "enabled") + private boolean enabled; + + @Type(type = "details") + @Column(name = "details") + private IntegrationTypeDetails details; + + @OneToMany(mappedBy = "type", fetch = FetchType.LAZY, orphanRemoval = true) + private Set integrations = Sets.newHashSet(); + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationTypeDetails.java b/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationTypeDetails.java new file mode 100644 index 00000000..5f277852 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/integration/IntegrationTypeDetails.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.integration; + +import com.epam.reportportal.auth.commons.JsonbUserType; +import java.io.Serializable; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Yauheni_Martynau + */ +@Setter +@Getter +public class IntegrationTypeDetails extends JsonbUserType implements Serializable { + + private Map details; + + @Override + public Class returnedClass() { + return IntegrationTypeDetails.class; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/item/issue/IssueGroup.java b/src/main/java/com/epam/reportportal/auth/entity/item/issue/IssueGroup.java new file mode 100644 index 00000000..9c695055 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/item/issue/IssueGroup.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.item.issue; + +import com.epam.reportportal.auth.entity.enums.TestItemIssueGroup; +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; + +/** + * @author Pavel Bortnik + */ +@Setter +@Getter +@Entity +@Table(name = "issue_group", schema = "public") +public class IssueGroup implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "issue_group_id") + private Integer id; + + @Column(name = "issue_group") + @Enumerated(EnumType.STRING) + @Type(type = "pqsql_enum") + private TestItemIssueGroup testItemIssueGroup; + + public IssueGroup() { + } + + public IssueGroup(TestItemIssueGroup testItemIssueGroup) { + this.testItemIssueGroup = testItemIssueGroup; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IssueGroup that = (IssueGroup) o; + return testItemIssueGroup == that.testItemIssueGroup; + } + + @Override + public int hashCode() { + + return Objects.hash(testItemIssueGroup); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/item/issue/IssueType.java b/src/main/java/com/epam/reportportal/auth/entity/item/issue/IssueType.java new file mode 100644 index 00000000..472f9160 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/item/issue/IssueType.java @@ -0,0 +1,103 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.item.issue; + +import com.epam.reportportal.auth.entity.enums.PostgreSQLEnumType; +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.TypeDef; + +/** + * @author Pavel Bortnik + */ +@Setter +@Getter +@Entity +@TypeDef(name = "pqsql_enum", typeClass = PostgreSQLEnumType.class) +@Table(name = "issue_type", schema = "public", indexes = { + @Index(name = "issue_type_pk", unique = true, columnList = "id ASC")}) +public class IssueType implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false) + private Long id; + + @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "issue_group_id") + private IssueGroup issueGroup; + + @Column(name = "locator", length = 64) + private String locator; + + @Column(name = "issue_name", length = 256) + private String longName; + + @Column(name = "abbreviation", length = 64) + private String shortName; + + @Column(name = "hex_color", length = 7) + private String hexColor; + + public IssueType() { + } + + public IssueType(IssueGroup issueGroup, String locator, String longName, String shortName, + String hexColor) { + this.issueGroup = issueGroup; + this.locator = locator; + this.longName = longName; + this.shortName = shortName; + this.hexColor = hexColor; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IssueType issueType = (IssueType) o; + return Objects.equals(id, issueType.id) && Objects.equals(issueGroup, issueType.issueGroup) + && Objects.equals(locator, + issueType.locator + ) && Objects.equals(longName, issueType.longName) && Objects.equals( + shortName, + issueType.shortName + ) && Objects.equals(hexColor, issueType.hexColor); + } + + @Override + public int hashCode() { + return Objects.hash(id, issueGroup, locator, longName, shortName, hexColor); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistration.java b/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistration.java new file mode 100644 index 00000000..713b2d7a --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistration.java @@ -0,0 +1,156 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.oauth; + +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Andrei Varabyeu + */ +@Getter +@Entity +@Table(name = "oauth_registration", schema = "public") +public class OAuthRegistration implements Serializable { + + @Setter + @Id + @Column(name = "id") + private String id; + + @Setter + @Column(name = "client_id") + private String clientId; + + @Setter + @Column(name = "client_secret") + private String clientSecret; + + @Setter + @Column(name = "client_auth_method") + private String clientAuthMethod; + + @Setter + @Column(name = "auth_grant_type") + private String authGrantType; + + @Setter + @Column(name = "redirect_uri_template") + private String redirectUrlTemplate; + + @Setter + @Column(name = "authorization_uri") + private String authorizationUri; + + @Setter + @Column(name = "token_uri") + private String tokenUri; + + @Setter + @Column(name = "user_info_endpoint_uri") + private String userInfoEndpointUri; + + @Setter + @Column(name = "user_info_endpoint_name_attr") + private String userInfoEndpointNameAttribute; + + @Setter + @Column(name = "jwk_set_uri") + private String jwkSetUri; + + @Setter + @Column(name = "client_name") + private String clientName; + + @OneToMany(mappedBy = "registration", fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, + CascadeType.MERGE, + CascadeType.REMOVE}, orphanRemoval = true) + private Set scopes; + + @OneToMany(mappedBy = "registration", fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, + CascadeType.MERGE, + CascadeType.REMOVE}, orphanRemoval = true) + private Set restrictions; + + public void setScopes(Set scopes) { + if (this.scopes == null) { + this.scopes = scopes; + } else { + this.scopes.retainAll(scopes); + this.scopes.addAll(scopes); + } + } + + public void setRestrictions(Set restrictions) { + if (this.restrictions == null) { + this.restrictions = restrictions; + } else { + this.restrictions.retainAll(restrictions); + this.restrictions.addAll(restrictions); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OAuthRegistration that = (OAuthRegistration) o; + return Objects.equals(id, that.id) && Objects.equals(clientId, that.clientId) && Objects.equals( + clientSecret, that.clientSecret) + && Objects.equals(clientAuthMethod, that.clientAuthMethod) && Objects.equals(authGrantType, + that.authGrantType) + && Objects.equals(redirectUrlTemplate, that.redirectUrlTemplate) && Objects.equals( + authorizationUri, that.authorizationUri) + && Objects.equals(tokenUri, that.tokenUri) && Objects.equals(userInfoEndpointUri, + that.userInfoEndpointUri) + && Objects.equals(userInfoEndpointNameAttribute, that.userInfoEndpointNameAttribute) + && Objects.equals(jwkSetUri, + that.jwkSetUri + ) && Objects.equals(clientName, that.clientName); + } + + @Override + public int hashCode() { + return Objects.hash(id, + clientId, + clientSecret, + clientAuthMethod, + authGrantType, + redirectUrlTemplate, + authorizationUri, + tokenUri, + userInfoEndpointUri, + userInfoEndpointNameAttribute, + jwkSetUri, + clientName + ); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistrationRestriction.java b/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistrationRestriction.java new file mode 100644 index 00000000..4ebc62eb --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistrationRestriction.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.oauth; + +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@Entity +@Table(name = "oauth_registration_restriction", schema = "public") +public class OAuthRegistrationRestriction implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @ManyToOne + @JoinColumn(name = "oauth_registration_fk") + private OAuthRegistration registration; + + @Column(name = "type") + private String type; + + @Column(name = "value") + private String value; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OAuthRegistrationRestriction that = (OAuthRegistrationRestriction) o; + return Objects.equals(type, that.type) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(type, value); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistrationScope.java b/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistrationScope.java new file mode 100644 index 00000000..3f7760bc --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/oauth/OAuthRegistrationScope.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.oauth; + +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Andrei Varabyeu + */ +@Setter +@Getter +@Entity +@Table(name = "oauth_registration_scope", schema = "public") +public class OAuthRegistrationScope implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "scope") + private String scope; + + @ManyToOne + @JoinColumn(name = "oauth_registration_fk") + private OAuthRegistration registration; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OAuthRegistrationScope that = (OAuthRegistrationScope) o; + return Objects.equals(scope, that.scope); + } + + @Override + public int hashCode() { + return Objects.hash(scope); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/Project.java b/src/main/java/com/epam/reportportal/auth/entity/project/Project.java new file mode 100644 index 00000000..e10c4b6f --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/Project.java @@ -0,0 +1,138 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import com.epam.reportportal.auth.dao.converters.JpaInstantConverter; +import com.epam.reportportal.auth.entity.Metadata; +import com.epam.reportportal.auth.entity.enums.ProjectType; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.user.ProjectUser; +import com.google.common.collect.Sets; +import java.io.Serializable; +import java.time.Instant; +import java.util.Objects; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import javax.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; + +/** + * @author Ivan Budayeu + */ +@Entity +@TypeDef(name = "json", typeClass = Metadata.class) +@Table(name = "project", schema = "public") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class Project implements Serializable { + + private static final long serialVersionUID = -263516611; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false, precision = 64) + private Long id; + + @Column(name = "name") + private String name; + + @Column(name = "project_type") + @Enumerated(EnumType.STRING) + private ProjectType projectType; + + @OneToMany(mappedBy = "project", cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY) + @OrderBy("creationDate desc") + private Set integrations = Sets.newHashSet(); + + @OneToMany(mappedBy = "project", cascade = {CascadeType.PERSIST}, fetch = FetchType.LAZY) + private Set projectAttributes = Sets.newHashSet(); + + @OneToMany(mappedBy = "project", cascade = {CascadeType.PERSIST, + CascadeType.MERGE, CascadeType.REMOVE}, fetch = FetchType.LAZY) + @OrderBy(value = "issue_type_id") + private Set projectIssueTypes = Sets.newHashSet(); + + /* Not required in service-authorization + @OneToMany(mappedBy = "project", cascade = { + CascadeType.PERSIST}, fetch = FetchType.EAGER, orphanRemoval = true) + private Set senderCases = Sets.newHashSet(); + */ + + @Column(name = "creation_date") + @Convert(converter = JpaInstantConverter.class) + private Instant creationDate; + + @Type(type = "json") + @Column(name = "metadata") + private Metadata metadata; + + @Column(name = "organization") + private String organization; + + @Column(name = "allocated_storage", updatable = false) + private long allocatedStorage; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "project", cascade = CascadeType.PERSIST) + private Set users = Sets.newHashSet(); + + public Project(Long id, String name) { + this.id = id; + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Project project = (Project) o; + return Objects.equals(name, project.name) && Objects.equals(allocatedStorage, + project.allocatedStorage) && Objects.equals( + creationDate, + project.creationDate + ) && Objects.equals(metadata, project.metadata); + } + + @Override + public int hashCode() { + + return Objects.hash(name, creationDate, metadata, allocatedStorage); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAnalyzerConfig.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAnalyzerConfig.java new file mode 100644 index 00000000..e66409e0 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAnalyzerConfig.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import java.io.Serializable; + +/** + * @author Pavel Bortnik + */ +public class ProjectAnalyzerConfig implements Serializable { + + public static final int MIN_DOC_FREQ = 1; + public static final int MIN_TERM_FREQ = 1; + public static final int MIN_SHOULD_MATCH = 95; + public static final int NUMBER_OF_LOG_LINES = -1; + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAttribute.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAttribute.java new file mode 100644 index 00000000..b2e1a735 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAttribute.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import com.epam.reportportal.auth.entity.attribute.Attribute; +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Andrey Plisunov + */ +@Setter +@Getter +@Entity +@Table(name = "project_attribute") +@IdClass(ProjectAttributeKey.class) +public class ProjectAttribute implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @ManyToOne + @JoinColumn(name = "attribute_id") + private Attribute attribute; + + @Column(name = "value") + private String value; + + @Id + @ManyToOne + @JoinColumn(name = "project_id") + private Project project; + + public ProjectAttribute() { + } + + public ProjectAttribute(Attribute attribute, String value, Project project) { + this.attribute = attribute; + this.value = value; + this.project = project; + } + + public ProjectAttribute withAttribute(Attribute attribute) { + this.attribute = attribute; + return this; + } + + public ProjectAttribute withProject(Project project) { + this.project = project; + return this; + } + + public ProjectAttribute withValue(String value) { + this.value = value; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectAttribute that = (ProjectAttribute) o; + return Objects.equals(attribute, that.attribute) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + + return Objects.hash(attribute, value); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAttributeKey.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAttributeKey.java new file mode 100644 index 00000000..0c1724fd --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectAttributeKey.java @@ -0,0 +1,64 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import com.epam.reportportal.auth.entity.attribute.Attribute; +import java.io.Serializable; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +/** + * @author Andrey Plisunov + */ +@Setter +@Getter +public class ProjectAttributeKey implements Serializable { + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "project_id", nullable = false, insertable = false, updatable = false) + private Project project; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "attribute_id", nullable = false, insertable = false, updatable = false) + private Attribute attribute; + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).append(project).append(attribute).toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof ProjectAttributeKey)) { + return false; + } + + ProjectAttributeKey projectAttributeKey = (ProjectAttributeKey) obj; + + return new EqualsBuilder().append(project.getId(), projectAttributeKey.project.getId()) + .append(attribute.getId(), projectAttributeKey.attribute.getId()) + .isEquals(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectIssueType.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectIssueType.java new file mode 100644 index 00000000..faa73c16 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectIssueType.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import com.epam.reportportal.auth.entity.item.issue.IssueType; +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Pavel Bortnik + */ +@Setter +@Getter +@Entity +@Table(name = "issue_type_project") +@IdClass(ProjectIssueTypeKey.class) +public class ProjectIssueType implements Serializable { + + @Id + @ManyToOne + @JoinColumn(name = "issue_type_id") + private IssueType issueType; + + @Id + @ManyToOne + @JoinColumn(name = "project_id") + private Project project; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectIssueType that = (ProjectIssueType) o; + return Objects.equals(issueType, that.issueType) && Objects.equals(project, that.project); + } + + @Override + public int hashCode() { + + return Objects.hash(issueType, project); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectIssueTypeKey.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectIssueTypeKey.java new file mode 100644 index 00000000..67ce8fed --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectIssueTypeKey.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import com.epam.reportportal.auth.entity.item.issue.IssueType; +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Pavel Bortnik + */ +@Setter +@Getter +public class ProjectIssueTypeKey implements Serializable { + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "project_id", nullable = false, insertable = false, updatable = false) + private Project project; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "issue_type_id", nullable = false, insertable = false, updatable = false) + private IssueType issueType; + + public ProjectIssueTypeKey() { + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectIssueTypeKey that = (ProjectIssueTypeKey) o; + return Objects.equals(project, that.project) && Objects.equals(issueType, that.issueType); + } + + @Override + public int hashCode() { + return Objects.hash(project, issueType); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectRole.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectRole.java new file mode 100644 index 00000000..08db95b8 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectRole.java @@ -0,0 +1,65 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import java.util.Arrays; +import java.util.Optional; + +/** + * @author Ivan Budayeu + */ +public enum ProjectRole implements Comparable { + + OPERATOR(0, "Operator"), + CUSTOMER(1, "Customer"), + MEMBER(2, "Member"), + PROJECT_MANAGER(3, "Project manager"); + + private final int roleLevel; + private final String roleName; + + ProjectRole(int level, String roleName) { + this.roleLevel = level; + this.roleName = roleName; + } + + public boolean higherThan(ProjectRole other) { + return this.roleLevel > other.roleLevel; + } + + public boolean lowerThan(ProjectRole other) { + return this.roleLevel < other.roleLevel; + } + + public boolean sameOrHigherThan(ProjectRole other) { + return this.roleLevel >= other.roleLevel; + } + + public boolean sameOrLowerThan(ProjectRole other) { + return this.roleLevel <= other.roleLevel; + } + + public static Optional forName(final String name) { + return Arrays.stream(ProjectRole.values()).filter(role -> role.name().equalsIgnoreCase(name)) + .findAny(); + } + + public String getRoleName() { + return roleName; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/project/ProjectUtils.java b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectUtils.java new file mode 100644 index 00000000..66bf9daf --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/project/ProjectUtils.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.project; + +import static java.util.Optional.ofNullable; + +import com.epam.reportportal.auth.entity.attribute.Attribute; +import com.epam.reportportal.auth.entity.enums.ProjectAttributeEnum; +import com.epam.reportportal.auth.entity.enums.TestItemIssueGroup; +import com.epam.reportportal.auth.entity.item.issue.IssueType; +import com.epam.reportportal.auth.rules.commons.validation.Suppliers; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Project related utility methods + * + * @author Andrei_Ramanchuk + */ +public class ProjectUtils { + + public static final String INIT_FROM = "reportportal@example.com"; + public static final String PERSONAL_PROJECT_POSTFIX_REGEX = "_personal(_?[0-9]+)?$"; + public static final String LINE_START_SYMBOL = "^"; + + private static final String OWNER = "OWNER"; + + private ProjectUtils() { + + } + + /** + * @return Generated default project configuration + */ + public static Set defaultProjectAttributes(Project project, + Set defaultAttributes) { + + Map attributes = defaultAttributes.stream() + .collect(Collectors.toMap(Attribute::getName, a -> a)); + + Set projectAttributes = new HashSet<>(defaultAttributes.size()); + + Arrays.stream(ProjectAttributeEnum.values()) + .map(ProjectAttributeEnum::getAttribute) + .forEach(pa -> ofNullable(attributes.get(pa)).ifPresent(attr -> { + ProjectAttribute projectAttribute = new ProjectAttribute(); + projectAttribute.setAttribute(attr); + projectAttribute.setProject(project); + + projectAttribute.setValue(ProjectAttributeEnum.findByAttributeName(pa) + .orElseThrow(() -> new ReportPortalException(ErrorType.BAD_REQUEST_ERROR, + Suppliers.formattedSupplier("Attribute - {} was not found", pa).get() + )) + .getDefaultValue()); + + projectAttributes.add(projectAttribute); + })); + + return projectAttributes; + + } + + public static Set defaultIssueTypes(Project project, + List defaultIssueTypes) { + + Map issueTypes = defaultIssueTypes.stream() + .collect(Collectors.toMap(IssueType::getLocator, i -> i)); + + Set projectIssueTypes = new HashSet<>(defaultIssueTypes.size()); + Arrays.stream(TestItemIssueGroup.values()) + .map(TestItemIssueGroup::getLocator) + .forEach(loc -> ofNullable(issueTypes.get(loc)).ifPresent(it -> { + ProjectIssueType projectIssueType = new ProjectIssueType(); + projectIssueType.setIssueType(it); + projectIssueType.setProject(project); + projectIssueTypes.add(projectIssueType); + })); + return projectIssueTypes; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/user/ProjectUser.java b/src/main/java/com/epam/reportportal/auth/entity/user/ProjectUser.java new file mode 100644 index 00000000..595dfb45 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/user/ProjectUser.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.user; + +import com.epam.reportportal.auth.entity.enums.PostgreSQLEnumType; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.project.ProjectRole; +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; + +/** + * @author Andrei Varabyeu + */ +@Setter +@Getter +@Entity +@TypeDef(name = "pqsql_enum", typeClass = PostgreSQLEnumType.class) +@Table(name = "project_user", schema = "public") +public class ProjectUser implements Serializable { + + @EmbeddedId + private ProjectUserId id = new ProjectUserId(); + + @ManyToOne(fetch = FetchType.LAZY) + @MapsId("projectId") + private Project project; + + @ManyToOne(fetch = FetchType.LAZY) + @MapsId("userId") + private User user; + + @Column(name = "project_role") + @Enumerated(EnumType.STRING) + @Type(type = "pqsql_enum") + private ProjectRole projectRole; + + public ProjectUser withProjectUserId(ProjectUserId id) { + this.id = id; + return this; + } + + public ProjectUser withUser(User user) { + this.user = user; + return this; + } + + public ProjectUser withProject(Project project) { + this.project = project; + return this; + } + + public ProjectUser withProjectRole(ProjectRole projectRole) { + this.projectRole = projectRole; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectUser that = (ProjectUser) o; + return Objects.equals(id, that.id) && Objects.equals(project, that.project) && Objects.equals( + user, that.user) + && projectRole == that.projectRole; + } + + @Override + public int hashCode() { + return Objects.hash(id, project, user, projectRole); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/user/ProjectUserId.java b/src/main/java/com/epam/reportportal/auth/entity/user/ProjectUserId.java new file mode 100644 index 00000000..5984d2e2 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/user/ProjectUserId.java @@ -0,0 +1,60 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.user; + +import java.io.Serializable; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Andrei Varabyeu + */ +@Setter +@Getter +@Embeddable +public class ProjectUserId implements Serializable { + + @Column(name = "user_id") + private Long userId; + + @Column(name = "project_id") + private Long projectId; + + public ProjectUserId() { + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectUserId that = (ProjectUserId) o; + return Objects.equals(userId, that.userId) && Objects.equals(projectId, that.projectId); + } + + @Override + public int hashCode() { + + return Objects.hash(userId, projectId); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/user/User.java b/src/main/java/com/epam/reportportal/auth/entity/user/User.java new file mode 100644 index 00000000..271facd7 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/user/User.java @@ -0,0 +1,125 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.user; + +import com.epam.reportportal.auth.entity.Metadata; +import com.google.common.collect.Sets; +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; + +/** + * @author Andrei Varabyeu + */ +@Getter +@Setter +@NoArgsConstructor +@Entity +@TypeDef(name = "meta", typeClass = Metadata.class) +@Table(name = "users", schema = "public") +@DynamicInsert +public class User implements Serializable { + + private static final long serialVersionUID = 923392981; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false, precision = 64) + private Long id; + + @Column(name = "uuid") + private UUID uuid; + + @Column(name = "external_id") + private String externalId; + + @Column(name = "active") + private Boolean active; + + @Column(name = "login") + private String login; + + @Column(name = "password") + private String password; + + @Column(name = "email") + private String email; + + @Column(name = "role") + @Enumerated(EnumType.STRING) + private UserRole role; + + @Column(name = "full_name") + private String fullName; + + @Column(name = "expired") + private boolean isExpired; + + @Column(name = "metadata") + @Type(type = "meta") + private Metadata metadata; + + @Column(name = "attachment") + private String attachment; + + @Column(name = "attachment_thumbnail") + private String attachmentThumbnail; + + @Column(name = "type") + @Enumerated(EnumType.STRING) + private UserType userType; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = {CascadeType.PERSIST, + CascadeType.MERGE, CascadeType.REFRESH}) + private Set projects = Sets.newHashSet(); + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(id, user.id) && Objects.equals(uuid, user.uuid) + && Objects.equals(login, user.login) && Objects.equals(email, user.email); + } + + @Override + public int hashCode() { + return Objects.hash(id, uuid, login, email); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/user/UserRole.java b/src/main/java/com/epam/reportportal/auth/entity/user/UserRole.java new file mode 100644 index 00000000..e00ae5ce --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/user/UserRole.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.user; + +import java.util.Arrays; +import java.util.Optional; + +/** + * UserRole representation
Role has more rights than the following one. So, Administrator is + * more privileged than User. + * + * @author Andrei Varabyeu + */ +public enum UserRole { + + USER, + ADMINISTRATOR; + + public static final String ROLE_PREFIX = "ROLE_"; + + public static Optional findByName(String name) { + return Arrays.stream(UserRole.values()).filter(role -> role.name().equals(name)).findAny(); + } + + + public String getAuthority() { + return ROLE_PREFIX + this.name(); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/entity/user/UserType.java b/src/main/java/com/epam/reportportal/auth/entity/user/UserType.java new file mode 100644 index 00000000..668b890f --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/entity/user/UserType.java @@ -0,0 +1,52 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.entity.user; + +import java.util.Arrays; +import java.util.Optional; + +/** + * User Type enumeration
Used for supporting different project types processing + * + * @author Andrei Varabyeu + */ +public enum UserType { + + //@formatter:off + INTERNAL, + UPSA, + GITHUB, + LDAP, + SAML, + + SCIM; + //@formatter:on + + public static UserType getByName(String type) { + return UserType.valueOf(type); + } + + public static Optional findByName(String name) { + return Arrays.stream(UserType.values()) + .filter(type -> type.name().equalsIgnoreCase(name)) + .findAny(); + } + + public static boolean isPresent(String name) { + return findByName(name).isPresent(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/event/ActivityEventHandler.java b/src/main/java/com/epam/reportportal/auth/event/ActivityEventHandler.java index b6f38474..5a2ece82 100644 --- a/src/main/java/com/epam/reportportal/auth/event/ActivityEventHandler.java +++ b/src/main/java/com/epam/reportportal/auth/event/ActivityEventHandler.java @@ -16,8 +16,8 @@ package com.epam.reportportal.auth.event; +import com.epam.reportportal.auth.entity.activity.Activity; import com.epam.reportportal.auth.event.activity.ActivityEvent; -import com.epam.ta.reportportal.entity.activity.Activity; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEvent.java b/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEvent.java index 597f2c4f..714b4c39 100644 --- a/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEvent.java +++ b/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEvent.java @@ -16,7 +16,7 @@ package com.epam.reportportal.auth.event; -import com.epam.ta.reportportal.entity.integration.IntegrationType; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import org.springframework.context.ApplicationEvent; /** diff --git a/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEventHandler.java b/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEventHandler.java index 172f73d8..eeee1e2a 100644 --- a/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEventHandler.java +++ b/src/main/java/com/epam/reportportal/auth/event/SamlProvidersReloadEventHandler.java @@ -16,10 +16,10 @@ package com.epam.reportportal.auth.event; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.converter.SamlConverter; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; import java.util.List; import org.springframework.context.ApplicationListener; import org.springframework.security.saml.provider.SamlServerConfiguration; diff --git a/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationFailureEventHandler.java b/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationFailureEventHandler.java index 2ef8f2b5..7da1e46c 100644 --- a/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationFailureEventHandler.java +++ b/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationFailureEventHandler.java @@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.context.ApplicationListener; import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; -import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher; import org.springframework.stereotype.Component; /** diff --git a/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationSuccessEventHandler.java b/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationSuccessEventHandler.java index c72e3e2e..7775cfdf 100644 --- a/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationSuccessEventHandler.java +++ b/src/main/java/com/epam/reportportal/auth/event/UiAuthenticationSuccessEventHandler.java @@ -16,14 +16,14 @@ package com.epam.reportportal.auth.event; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.user.User; import com.epam.reportportal.auth.integration.saml.ReportPortalSamlAuthentication; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.project.Project; -import com.epam.ta.reportportal.entity.user.User; -import com.epam.ta.reportportal.util.PersonalProjectService; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.epam.reportportal.auth.util.PersonalProjectService; import org.apache.commons.collections4.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.EventListener; @@ -57,9 +57,9 @@ public UiAuthenticationSuccessEventHandler(UserRepository userRepository, } /** - * Handles the UI user signed-in event. Updates the last login date for the user - * and generates a personal project if the user has no projects. - * Also, if the user is inactive, it will be activated for SAML authentication. + * Handles the UI user signed-in event. Updates the last login date for the user and generates a + * personal project if the user has no projects. Also, if the user is inactive, it will be + * activated for SAML authentication. * * @param event the UI user signed-in event */ @@ -80,16 +80,15 @@ public void onApplicationEvent(UiUserSignedInEvent event) { private ReportPortalUser acquireUser(Authentication authentication) { if (authentication instanceof ReportPortalSamlAuthentication rpAuth) { - userRepository.findByLogin(rpAuth.getPrincipal()) + return userRepository.findByLogin(rpAuth.getPrincipal()) .filter(user -> !user.getActive()) - .ifPresent(user -> { + .map(user -> { user.setActive(true); - userRepository.save(user); - }); - return userRepository.findUserDetails(rpAuth.getPrincipal()) - .orElseThrow(() -> new ReportPortalException( - ErrorType.USER_NOT_FOUND, rpAuth.getPrincipal() - )); + return userRepository.save(user); + }) + .map(user -> ReportPortalUser.userBuilder().fromUser(user)) + .orElseThrow(() -> + new ReportPortalException(ErrorType.USER_NOT_FOUND, rpAuth.getPrincipal())); } else { if (!((ReportPortalUser) authentication.getPrincipal()).isEnabled()) { SecurityContextHolder.clearContext(); @@ -98,4 +97,4 @@ private ReportPortalUser acquireUser(Authentication authentication) { return (ReportPortalUser) authentication.getPrincipal(); } } -} \ No newline at end of file +} diff --git a/src/main/java/com/epam/reportportal/auth/event/activity/ActivityEvent.java b/src/main/java/com/epam/reportportal/auth/event/activity/ActivityEvent.java index 89ff90b3..3dd908f0 100644 --- a/src/main/java/com/epam/reportportal/auth/event/activity/ActivityEvent.java +++ b/src/main/java/com/epam/reportportal/auth/event/activity/ActivityEvent.java @@ -16,7 +16,7 @@ package com.epam.reportportal.auth.event.activity; -import com.epam.ta.reportportal.entity.activity.Activity; +import com.epam.reportportal.auth.entity.activity.Activity; public interface ActivityEvent { diff --git a/src/main/java/com/epam/reportportal/auth/event/activity/AssignUserEvent.java b/src/main/java/com/epam/reportportal/auth/event/activity/AssignUserEvent.java index e0da44e8..dd38e789 100644 --- a/src/main/java/com/epam/reportportal/auth/event/activity/AssignUserEvent.java +++ b/src/main/java/com/epam/reportportal/auth/event/activity/AssignUserEvent.java @@ -16,14 +16,14 @@ package com.epam.reportportal.auth.event.activity; -import static com.epam.ta.reportportal.entity.activity.ActivityAction.ASSIGN_USER; - -import com.epam.ta.reportportal.builder.ActivityBuilder; -import com.epam.ta.reportportal.entity.activity.Activity; -import com.epam.ta.reportportal.entity.activity.EventAction; -import com.epam.ta.reportportal.entity.activity.EventObject; -import com.epam.ta.reportportal.entity.activity.EventPriority; -import com.epam.ta.reportportal.entity.activity.EventSubject; +import static com.epam.reportportal.auth.entity.activity.ActivityAction.ASSIGN_USER; + +import com.epam.reportportal.auth.builder.ActivityBuilder; +import com.epam.reportportal.auth.entity.activity.Activity; +import com.epam.reportportal.auth.entity.activity.EventAction; +import com.epam.reportportal.auth.entity.activity.EventObject; +import com.epam.reportportal.auth.entity.activity.EventPriority; +import com.epam.reportportal.auth.entity.activity.EventSubject; /** * Event publish when user is assigned to a project. diff --git a/src/main/java/com/epam/reportportal/auth/event/activity/ProjectCreatedEvent.java b/src/main/java/com/epam/reportportal/auth/event/activity/ProjectCreatedEvent.java index f220d9f7..a749849b 100644 --- a/src/main/java/com/epam/reportportal/auth/event/activity/ProjectCreatedEvent.java +++ b/src/main/java/com/epam/reportportal/auth/event/activity/ProjectCreatedEvent.java @@ -16,13 +16,13 @@ package com.epam.reportportal.auth.event.activity; -import com.epam.ta.reportportal.builder.ActivityBuilder; -import com.epam.ta.reportportal.entity.activity.Activity; -import com.epam.ta.reportportal.entity.activity.ActivityAction; -import com.epam.ta.reportportal.entity.activity.EventAction; -import com.epam.ta.reportportal.entity.activity.EventObject; -import com.epam.ta.reportportal.entity.activity.EventPriority; -import com.epam.ta.reportportal.entity.activity.EventSubject; +import com.epam.reportportal.auth.builder.ActivityBuilder; +import com.epam.reportportal.auth.entity.activity.Activity; +import com.epam.reportportal.auth.entity.activity.ActivityAction; +import com.epam.reportportal.auth.entity.activity.EventAction; +import com.epam.reportportal.auth.entity.activity.EventObject; +import com.epam.reportportal.auth.entity.activity.EventPriority; +import com.epam.reportportal.auth.entity.activity.EventSubject; /** * Publish an event when project is created. diff --git a/src/main/java/com/epam/reportportal/auth/event/activity/UserCreatedEvent.java b/src/main/java/com/epam/reportportal/auth/event/activity/UserCreatedEvent.java index 517a3c1a..8e73e2c7 100644 --- a/src/main/java/com/epam/reportportal/auth/event/activity/UserCreatedEvent.java +++ b/src/main/java/com/epam/reportportal/auth/event/activity/UserCreatedEvent.java @@ -16,13 +16,13 @@ package com.epam.reportportal.auth.event.activity; -import com.epam.ta.reportportal.builder.ActivityBuilder; -import com.epam.ta.reportportal.entity.activity.Activity; -import com.epam.ta.reportportal.entity.activity.ActivityAction; -import com.epam.ta.reportportal.entity.activity.EventAction; -import com.epam.ta.reportportal.entity.activity.EventObject; -import com.epam.ta.reportportal.entity.activity.EventPriority; -import com.epam.ta.reportportal.entity.activity.EventSubject; +import com.epam.reportportal.auth.builder.ActivityBuilder; +import com.epam.reportportal.auth.entity.activity.Activity; +import com.epam.reportportal.auth.entity.activity.ActivityAction; +import com.epam.reportportal.auth.entity.activity.EventAction; +import com.epam.reportportal.auth.entity.activity.EventObject; +import com.epam.reportportal.auth.entity.activity.EventPriority; +import com.epam.reportportal.auth.entity.activity.EventSubject; /** * Publish an event when user is created. diff --git a/src/main/java/com/epam/reportportal/auth/filesystem/DataEncoder.java b/src/main/java/com/epam/reportportal/auth/filesystem/DataEncoder.java new file mode 100644 index 00000000..04847552 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/filesystem/DataEncoder.java @@ -0,0 +1,57 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.filesystem; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +/** + * @author Dzianis_Shybeka + *

+ * Class to encode/decode values to url compatible format + */ +@Component +public class DataEncoder { + + /** + * Encode provided data. + * + * @param data + * @return + */ + public String encode(String data) { + + return StringUtils.isEmpty(data) ? + data : + Base64.getUrlEncoder().withoutPadding() + .encodeToString(data.getBytes(StandardCharsets.UTF_8)); + } + + /** + * Decode provided data. + * + * @param data + * @return + */ + public String decode(String data) { + + return StringUtils.isEmpty(data) ? data + : new String(Base64.getUrlDecoder().decode(data), StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/filesystem/DataStore.java b/src/main/java/com/epam/reportportal/auth/filesystem/DataStore.java new file mode 100644 index 00000000..39ed8703 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/filesystem/DataStore.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.filesystem; + +import java.io.InputStream; +import java.util.List; + +/** + * @author Dzianis_Shybeka + */ +public interface DataStore { + + String save(String fileName, InputStream inputStream); + + InputStream load(String filePath); + + boolean exists(String filePath); + + void delete(String filePath); + + void deleteAll(List filePaths, String bucketName); + + void deleteContainer(String bucketName); +} diff --git a/src/main/java/com/epam/reportportal/auth/filesystem/LocalDataStore.java b/src/main/java/com/epam/reportportal/auth/filesystem/LocalDataStore.java new file mode 100644 index 00000000..78eca0ea --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/filesystem/LocalDataStore.java @@ -0,0 +1,158 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.filesystem; + +import com.epam.reportportal.auth.entity.enums.FeatureFlag; +import com.epam.reportportal.auth.filesystem.distributed.s3.StoredFile; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.epam.reportportal.auth.util.FeatureFlagHandler; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.domain.Blob; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Dzianis_Shybeka + */ +public class LocalDataStore implements DataStore { + + private static final Logger LOGGER = LoggerFactory.getLogger(LocalDataStore.class); + private final BlobStore blobStore; + + private final FeatureFlagHandler featureFlagHandler; + + private final String bucketPrefix; + + private final String bucketPostfix; + + private final String defaultBucketName; + + public LocalDataStore(BlobStore blobStore, FeatureFlagHandler featureFlagHandler, + String bucketPrefix, String bucketPostfix, String defaultBucketName) { + this.blobStore = blobStore; + this.featureFlagHandler = featureFlagHandler; + this.bucketPrefix = bucketPrefix; + this.bucketPostfix = Objects.requireNonNullElse(bucketPostfix, ""); + this.defaultBucketName = defaultBucketName; + } + + @Override + public String save(String filePath, InputStream inputStream) { + if (filePath == null) { + return ""; + } + StoredFile storedFile = getStoredFile(filePath); + try { + if (!blobStore.containerExists(storedFile.bucket())) { + blobStore.createContainerInLocation(null, storedFile.bucket()); + } + Blob objectBlob = blobStore.blobBuilder(storedFile.filePath()).payload(inputStream) + .contentDisposition(storedFile.filePath()).contentLength(inputStream.available()) + .build(); + blobStore.putBlob(storedFile.bucket(), objectBlob); + return filePath; + } catch (IOException e) { + throw new ReportPortalException(ErrorType.INCORRECT_REQUEST, "Unable to save file", e); + } + } + + @Override + public InputStream load(String filePath) { + if (filePath == null) { + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, "Unable to find file"); + } + StoredFile storedFile = getStoredFile(filePath); + Blob fileBlob = blobStore.getBlob(storedFile.bucket(), storedFile.filePath()); + if (fileBlob != null) { + try { + return fileBlob.getPayload().openStream(); + } catch (IOException e) { + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, e.getMessage(), e); + } + } + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, "Unable to find file"); + } + + @Override + public boolean exists(String filePath) { + if (filePath == null) { + return false; + } + StoredFile storedFile = getStoredFile(filePath); + if (blobStore.containerExists(storedFile.bucket())) { + return blobStore.blobExists(storedFile.bucket(), storedFile.filePath()); + } else { + LOGGER.warn("Container '{}' does not exist", storedFile.bucket()); + return false; + } + } + + @Override + public void delete(String filePath) { + if (filePath == null) { + return; + } + StoredFile storedFile = getStoredFile(filePath); + try { + blobStore.removeBlob(storedFile.bucket(), storedFile.filePath()); + } catch (Exception e) { + throw new ReportPortalException(ErrorType.INCORRECT_REQUEST, "Unable to delete file", e); + } + } + + @Override + public void deleteAll(List filePaths, String bucketName) { + if (!featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + blobStore.removeBlobs(bucketPrefix + bucketName + bucketPostfix, filePaths); + } else { + blobStore.removeBlobs(bucketName, filePaths); + } + } + + @Override + public void deleteContainer(String bucketName) { + blobStore.deleteContainer(bucketName); + } + + private StoredFile getStoredFile(String filePath) { + if (featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + return new StoredFile(defaultBucketName, filePath); + } + Path targetPath = Paths.get(filePath); + int nameCount = targetPath.getNameCount(); + String bucketName; + if (nameCount > 1) { + bucketName = bucketPrefix + retrievePath(targetPath, 0, 1) + bucketPostfix; + return new StoredFile(bucketName, retrievePath(targetPath, 1, nameCount)); + } else { + bucketName = defaultBucketName; + return new StoredFile(bucketName, retrievePath(targetPath, 0, 1)); + } + } + + private String retrievePath(Path path, int beginIndex, int endIndex) { + return String.valueOf(path.subpath(beginIndex, endIndex)); + } +} + diff --git a/src/main/java/com/epam/reportportal/auth/filesystem/distributed/s3/S3DataStore.java b/src/main/java/com/epam/reportportal/auth/filesystem/distributed/s3/S3DataStore.java new file mode 100644 index 00000000..04e41c42 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/filesystem/distributed/s3/S3DataStore.java @@ -0,0 +1,199 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.filesystem.distributed.s3; + +import com.epam.reportportal.auth.entity.enums.FeatureFlag; +import com.epam.reportportal.auth.filesystem.DataStore; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.epam.reportportal.auth.util.FeatureFlagHandler; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.domain.Blob; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implimitation of basic operations with blob storages. + * + * @author Ivan Budayeu + */ +public class S3DataStore implements DataStore { + + private static final Logger LOGGER = LoggerFactory.getLogger(S3DataStore.class); + private static final Lock CREATE_BUCKET_LOCK = new ReentrantLock(); + public static final String UNABLE_TO_FIND_FILE = "Unable to find file"; + + private final BlobStore blobStore; + private final String bucketPrefix; + private final String bucketPostfix; + private final String defaultBucketName; + private final Location location; + + private final FeatureFlagHandler featureFlagHandler; + + /** + * Initialises {@link S3DataStore}. + * + * @param blobStore {@link BlobStore} + * @param bucketPrefix Prefix for bucket name + * @param bucketPostfix Postfix for bucket name + * @param defaultBucketName Name of default bucket to use + * @param region Region to use + * @param featureFlagHandler {@link FeatureFlagHandler} + */ + public S3DataStore(BlobStore blobStore, String bucketPrefix, String bucketPostfix, + String defaultBucketName, String region, FeatureFlagHandler featureFlagHandler) { + this.blobStore = blobStore; + this.bucketPrefix = bucketPrefix; + this.bucketPostfix = Objects.requireNonNullElse(bucketPostfix, ""); + this.defaultBucketName = defaultBucketName; + this.location = getLocationFromString(region); + this.featureFlagHandler = featureFlagHandler; + } + + @Override + public String save(String filePath, InputStream inputStream) { + if (filePath == null) { + return ""; + } + StoredFile storedFile = getStoredFile(filePath); + try { + if (!blobStore.containerExists(storedFile.bucket())) { + CREATE_BUCKET_LOCK.lock(); + try { + if (!blobStore.containerExists(storedFile.bucket())) { + blobStore.createContainerInLocation(location, storedFile.bucket()); + } + } finally { + CREATE_BUCKET_LOCK.unlock(); + } + } + + Blob objectBlob = blobStore.blobBuilder(storedFile.filePath()).payload(inputStream) + .contentDisposition(storedFile.filePath()).contentLength(inputStream.available()) + .build(); + blobStore.putBlob(storedFile.bucket(), objectBlob); + return Paths.get(filePath).toString(); + } catch (IOException e) { + LOGGER.error("Unable to save file '{}'", filePath, e); + throw new ReportPortalException(ErrorType.INCORRECT_REQUEST, "Unable to save file"); + } + } + + @Override + public InputStream load(String filePath) { + if (filePath == null) { + LOGGER.error(UNABLE_TO_FIND_FILE); + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, UNABLE_TO_FIND_FILE); + } + StoredFile storedFile = getStoredFile(filePath); + Blob fileBlob = blobStore.getBlob(storedFile.bucket(), storedFile.filePath()); + if (fileBlob != null) { + try { + return fileBlob.getPayload().openStream(); + } catch (IOException e) { + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, e.getMessage()); + } + } + LOGGER.error("Unable to find file '{}'", filePath); + throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, UNABLE_TO_FIND_FILE); + } + + @Override + public boolean exists(String filePath) { + if (filePath == null) { + return false; + } + StoredFile storedFile = getStoredFile(filePath); + return blobStore.blobExists(storedFile.bucket(), storedFile.filePath()); + } + + @Override + public void delete(String filePath) { + if (filePath == null) { + return; + } + StoredFile storedFile = getStoredFile(filePath); + try { + blobStore.removeBlob(storedFile.bucket(), storedFile.filePath()); + } catch (Exception e) { + LOGGER.error("Unable to delete file '{}'", filePath, e); + throw new ReportPortalException(ErrorType.INCORRECT_REQUEST, "Unable to delete file"); + } + } + + @Override + public void deleteAll(List filePaths, String bucketName) { + if (!featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + blobStore.removeBlobs(bucketPrefix + bucketName + bucketPostfix, filePaths); + } else { + blobStore.removeBlobs(bucketName, filePaths); + } + } + + @Override + public void deleteContainer(String bucketName) { + if (!featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + blobStore.deleteContainer(bucketPrefix + bucketName + bucketPostfix); + } else { + blobStore.deleteContainer(bucketName); + } + } + + private StoredFile getStoredFile(String filePath) { + if (featureFlagHandler.isEnabled(FeatureFlag.SINGLE_BUCKET)) { + return new StoredFile(defaultBucketName, filePath); + } + Path targetPath = Paths.get(filePath); + int nameCount = targetPath.getNameCount(); + String bucketName; + if (nameCount > 1) { + bucketName = bucketPrefix + retrievePath(targetPath, 0, 1) + bucketPostfix; + return new StoredFile(bucketName, retrievePath(targetPath, 1, nameCount)); + } else { + bucketName = defaultBucketName; + return new StoredFile(bucketName, retrievePath(targetPath, 0, 1)); + } + } + + private Location getLocationFromString(String locationString) { + Location loc = null; + if (locationString != null) { + loc = new LocationBuilder() + .scope(LocationScope.REGION) + .id(locationString) + .description("region") + .build(); + } + return loc; + } + + private String retrievePath(Path path, int beginIndex, int endIndex) { + return String.valueOf(path.subpath(beginIndex, endIndex)); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/filesystem/distributed/s3/StoredFile.java b/src/main/java/com/epam/reportportal/auth/filesystem/distributed/s3/StoredFile.java new file mode 100644 index 00000000..177d8c47 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/filesystem/distributed/s3/StoredFile.java @@ -0,0 +1,24 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.filesystem.distributed.s3; + +/** + * @author Ivan Budayeu + */ +public record StoredFile(String bucket, String filePath) { + +} diff --git a/src/main/java/com/epam/reportportal/auth/integration/AbstractUserReplicator.java b/src/main/java/com/epam/reportportal/auth/integration/AbstractUserReplicator.java index 835e4c4a..5c7ebc0c 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/AbstractUserReplicator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/AbstractUserReplicator.java @@ -18,15 +18,16 @@ import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.binary.UserBinaryDataService; +import com.epam.reportportal.auth.commons.ContentTypeResolver; +import com.epam.reportportal.auth.dao.ProjectRepository; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.Metadata; +import com.epam.reportportal.auth.entity.attachment.BinaryData; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.user.User; import com.epam.reportportal.auth.oauth.UserSynchronizationException; -import com.epam.reportportal.commons.ContentTypeResolver; -import com.epam.ta.reportportal.binary.UserBinaryDataService; -import com.epam.ta.reportportal.dao.ProjectRepository; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.attachment.BinaryData; -import com.epam.ta.reportportal.entity.project.Project; -import com.epam.ta.reportportal.entity.user.User; -import com.epam.ta.reportportal.util.PersonalProjectService; +import com.epam.reportportal.auth.util.PersonalProjectService; import com.google.common.collect.Maps; import java.io.ByteArrayInputStream; import java.time.LocalDateTime; @@ -75,12 +76,12 @@ protected Project generatePersonalProject(User user) { * * @return Default meta info */ - protected com.epam.ta.reportportal.entity.Metadata defaultMetaData() { + protected Metadata defaultMetaData() { Map metaDataMap = new HashMap<>(); long nowInMillis = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(); metaDataMap.put("last_login", nowInMillis); metaDataMap.put("synchronizationDate", nowInMillis); - return new com.epam.ta.reportportal.entity.Metadata(metaDataMap); + return new Metadata(metaDataMap); } /** @@ -89,8 +90,8 @@ protected com.epam.ta.reportportal.entity.Metadata defaultMetaData() { * @param user User to be synchronized */ protected void updateSynchronizationDate(User user) { - com.epam.ta.reportportal.entity.Metadata metadata = ofNullable(user.getMetadata()).orElse( - new com.epam.ta.reportportal.entity.Metadata( + Metadata metadata = ofNullable(user.getMetadata()).orElse( + new Metadata( Maps.newHashMap())); metadata.getMetadata() .put("synchronizationDate", LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()); diff --git a/src/main/java/com/epam/reportportal/auth/integration/AuthIntegrationType.java b/src/main/java/com/epam/reportportal/auth/integration/AuthIntegrationType.java index 302464cb..a064c5c0 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/AuthIntegrationType.java +++ b/src/main/java/com/epam/reportportal/auth/integration/AuthIntegrationType.java @@ -18,14 +18,14 @@ import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.converter.ActiveDirectoryConverter; import com.epam.reportportal.auth.integration.converter.LdapConverter; import com.epam.reportportal.auth.integration.converter.SamlConverter; import com.epam.reportportal.auth.model.SamlResource; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; -import com.epam.reportportal.model.integration.auth.ActiveDirectoryResource; -import com.epam.reportportal.model.integration.auth.LdapResource; -import com.epam.ta.reportportal.entity.integration.Integration; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.ActiveDirectoryResource; +import com.epam.reportportal.auth.model.integration.auth.LdapResource; import java.util.Arrays; import java.util.Optional; import java.util.function.Function; diff --git a/src/main/java/com/epam/reportportal/auth/integration/builder/AuthIntegrationBuilder.java b/src/main/java/com/epam/reportportal/auth/integration/builder/AuthIntegrationBuilder.java index 038f9e9d..b6bf655c 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/builder/AuthIntegrationBuilder.java +++ b/src/main/java/com/epam/reportportal/auth/integration/builder/AuthIntegrationBuilder.java @@ -16,10 +16,9 @@ package com.epam.reportportal.auth.integration.builder; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import java.time.Instant; -import java.time.LocalDateTime; import javax.validation.constraints.NotNull; /** diff --git a/src/main/java/com/epam/reportportal/auth/integration/converter/ActiveDirectoryConverter.java b/src/main/java/com/epam/reportportal/auth/integration/converter/ActiveDirectoryConverter.java index 93fded2f..a0e9574e 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/converter/ActiveDirectoryConverter.java +++ b/src/main/java/com/epam/reportportal/auth/integration/converter/ActiveDirectoryConverter.java @@ -16,9 +16,9 @@ package com.epam.reportportal.auth.integration.converter; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.parameter.LdapParameter; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.reportportal.model.integration.auth.ActiveDirectoryResource; +import com.epam.reportportal.auth.model.integration.auth.ActiveDirectoryResource; import java.util.function.Function; /** diff --git a/src/main/java/com/epam/reportportal/auth/integration/converter/LdapConverter.java b/src/main/java/com/epam/reportportal/auth/integration/converter/LdapConverter.java index 9df57f71..55029710 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/converter/LdapConverter.java +++ b/src/main/java/com/epam/reportportal/auth/integration/converter/LdapConverter.java @@ -18,13 +18,13 @@ import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.parameter.LdapParameter; import com.epam.reportportal.auth.integration.parameter.ParameterUtils; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.reportportal.model.integration.auth.LdapAttributes; -import com.epam.reportportal.model.integration.auth.LdapResource; -import com.epam.reportportal.model.integration.auth.SynchronizationAttributesResource; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.LdapAttributes; +import com.epam.reportportal.auth.model.integration.auth.LdapResource; +import com.epam.reportportal.auth.model.integration.auth.SynchronizationAttributesResource; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; diff --git a/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRegistrationConverters.java b/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRegistrationConverters.java index 68ee025b..8511c8fe 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRegistrationConverters.java +++ b/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRegistrationConverters.java @@ -18,10 +18,10 @@ import static java.util.Optional.ofNullable; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistrationRestriction; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistrationScope; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistrationRestriction; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistrationScope; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import com.google.common.base.Preconditions; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRestrictionConverter.java b/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRestrictionConverter.java index 4260af38..493a0363 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRestrictionConverter.java +++ b/src/main/java/com/epam/reportportal/auth/integration/converter/OAuthRestrictionConverter.java @@ -18,9 +18,9 @@ import static java.util.Optional.ofNullable; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistrationRestriction; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistrationRestriction; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import java.util.HashMap; diff --git a/src/main/java/com/epam/reportportal/auth/integration/converter/SamlConverter.java b/src/main/java/com/epam/reportportal/auth/integration/converter/SamlConverter.java index 381b3f5c..895170f9 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/converter/SamlConverter.java +++ b/src/main/java/com/epam/reportportal/auth/integration/converter/SamlConverter.java @@ -29,12 +29,12 @@ import static com.epam.reportportal.auth.integration.parameter.SamlParameter.ROLES_ATTRIBUTE; import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.parameter.ParameterUtils; -import com.epam.reportportal.auth.model.SamlResource; import com.epam.reportportal.auth.model.SamlProvidersResource; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.SamlResource; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -67,21 +67,22 @@ public class SamlConverter { resource.setIdentityProviderName(integration.getName()); resource.setEnabled(integration.isEnabled()); - EMAIL_ATTRIBUTE.getParameter(integration).ifPresent(resource::setEmailAttribute); - FIRST_NAME_ATTRIBUTE.getParameter(integration).ifPresent(resource::setFirstNameAttribute); - LAST_NAME_ATTRIBUTE.getParameter(integration).ifPresent(resource::setLastNameAttribute); - FULL_NAME_ATTRIBUTE.getParameter(integration).ifPresent(resource::setFullNameAttribute); - IDP_ALIAS.getParameter(integration).ifPresent(resource::setIdentityProviderAlias); - IDP_METADATA_URL.getParameter(integration).ifPresent(resource::setIdentityProviderMetadataUrl); - IDP_URL.getParameter(integration).ifPresent(resource::setIdentityProviderUrl); - IDP_NAME_ID.getParameter(integration).ifPresent(resource::setIdentityProviderNameId); - ROLES_ATTRIBUTE.getParameter(integration).ifPresent(resource::setRolesAttribute); - final IntegrationType integrationType = integration.getType(); - ofNullable(integrationType.getDetails()).flatMap(typeDetails -> Optional.ofNullable(typeDetails.getDetails())) - .flatMap(BASE_PATH::getParameter) - .ifPresent(resource::setCallbackUrl); - return resource; - }; + EMAIL_ATTRIBUTE.getParameter(integration).ifPresent(resource::setEmailAttribute); + FIRST_NAME_ATTRIBUTE.getParameter(integration).ifPresent(resource::setFirstNameAttribute); + LAST_NAME_ATTRIBUTE.getParameter(integration).ifPresent(resource::setLastNameAttribute); + FULL_NAME_ATTRIBUTE.getParameter(integration).ifPresent(resource::setFullNameAttribute); + IDP_ALIAS.getParameter(integration).ifPresent(resource::setIdentityProviderAlias); + IDP_METADATA_URL.getParameter(integration).ifPresent(resource::setIdentityProviderMetadataUrl); + IDP_URL.getParameter(integration).ifPresent(resource::setIdentityProviderUrl); + IDP_NAME_ID.getParameter(integration).ifPresent(resource::setIdentityProviderNameId); + ROLES_ATTRIBUTE.getParameter(integration).ifPresent(resource::setRolesAttribute); + final IntegrationType integrationType = integration.getType(); + ofNullable(integrationType.getDetails()).flatMap( + typeDetails -> Optional.ofNullable(typeDetails.getDetails())) + .flatMap(BASE_PATH::getParameter) + .ifPresent(resource::setCallbackUrl); + return resource; + }; public static final Function, List> TO_EXTERNAL_PROVIDER_CONFIG = integrations -> { List externalProviders = integrations.stream() diff --git a/src/main/java/com/epam/reportportal/auth/integration/github/EmailResource.java b/src/main/java/com/epam/reportportal/auth/integration/github/EmailResource.java index 5d9584ca..7444184c 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/github/EmailResource.java +++ b/src/main/java/com/epam/reportportal/auth/integration/github/EmailResource.java @@ -16,8 +16,6 @@ package com.epam.reportportal.auth.integration.github; -import com.google.common.base.MoreObjects; -import java.util.Objects; import lombok.Data; /** diff --git a/src/main/java/com/epam/reportportal/auth/integration/github/GitHubClient.java b/src/main/java/com/epam/reportportal/auth/integration/github/GitHubClient.java index 0f905ec6..80b66262 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/github/GitHubClient.java +++ b/src/main/java/com/epam/reportportal/auth/integration/github/GitHubClient.java @@ -16,8 +16,8 @@ package com.epam.reportportal.auth.integration.github; -import com.google.common.base.Charsets; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import org.slf4j.Logger; @@ -51,7 +51,7 @@ private GitHubClient(String accessToken) { @Override public void handleError(ClientHttpResponse response) throws IOException { String errorMessage = - "Unable to load Github Data:" + new String(getResponseBody(response), Charsets.UTF_8); + "Unable to load Github Data:" + new String(getResponseBody(response), StandardCharsets.UTF_8); LOGGER.error(errorMessage); throw new AuthenticationServiceException(errorMessage); } @@ -82,7 +82,8 @@ public List getUserEmails() { public List getUserOrganizations(String user) { return getForObject(GITHUB_BASE_URL + "/user/orgs", - new ParameterizedTypeReference<>() {}, + new ParameterizedTypeReference<>() { + }, user); } diff --git a/src/main/java/com/epam/reportportal/auth/integration/github/GitHubTokenServices.java b/src/main/java/com/epam/reportportal/auth/integration/github/GitHubTokenServices.java index bf2ce861..f0e18256 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/github/GitHubTokenServices.java +++ b/src/main/java/com/epam/reportportal/auth/integration/github/GitHubTokenServices.java @@ -20,8 +20,8 @@ import static java.util.Collections.emptyList; import static java.util.Optional.ofNullable; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import com.google.common.base.Splitter; import java.io.Serializable; import java.util.Collections; diff --git a/src/main/java/com/epam/reportportal/auth/integration/github/GitHubUserReplicator.java b/src/main/java/com/epam/reportportal/auth/integration/github/GitHubUserReplicator.java index c98aac67..62b41708 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/github/GitHubUserReplicator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/github/GitHubUserReplicator.java @@ -16,26 +16,26 @@ package com.epam.reportportal.auth.integration.github; -import static com.epam.ta.reportportal.commons.EntityUtils.normalizeId; +import static com.epam.reportportal.auth.commons.EntityUtils.normalizeId; import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.binary.UserBinaryDataService; +import com.epam.reportportal.auth.commons.ContentTypeResolver; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.dao.ProjectRepository; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.Metadata; +import com.epam.reportportal.auth.entity.attachment.BinaryData; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.user.User; +import com.epam.reportportal.auth.entity.user.UserRole; +import com.epam.reportportal.auth.entity.user.UserType; import com.epam.reportportal.auth.integration.AbstractUserReplicator; import com.epam.reportportal.auth.oauth.UserSynchronizationException; -import com.epam.reportportal.commons.ContentTypeResolver; -import com.epam.reportportal.rules.commons.validation.BusinessRule; -import com.epam.ta.reportportal.binary.UserBinaryDataService; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.ta.reportportal.dao.ProjectRepository; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.Metadata; -import com.epam.ta.reportportal.entity.attachment.BinaryData; -import com.epam.ta.reportportal.entity.project.Project; -import com.epam.ta.reportportal.entity.user.User; -import com.epam.ta.reportportal.entity.user.UserRole; -import com.epam.ta.reportportal.entity.user.UserType; -import com.epam.ta.reportportal.util.PersonalProjectService; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.commons.validation.BusinessRule; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.util.PersonalProjectService; import com.google.common.base.Strings; import com.google.common.collect.Maps; import java.io.IOException; diff --git a/src/main/java/com/epam/reportportal/auth/integration/github/GithubEndpoint.java b/src/main/java/com/epam/reportportal/auth/integration/github/GithubEndpoint.java index 926d1d3e..1bf918df 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/github/GithubEndpoint.java +++ b/src/main/java/com/epam/reportportal/auth/integration/github/GithubEndpoint.java @@ -18,9 +18,9 @@ import static com.epam.reportportal.auth.integration.github.ExternalOauth2TokenConverter.UPSTREAM_TOKEN; -import com.epam.reportportal.rules.commons.validation.BusinessRule; -import com.epam.reportportal.rules.exception.ErrorType; import com.epam.reportportal.auth.OperationCompletionRS; +import com.epam.reportportal.auth.rules.commons.validation.BusinessRule; +import com.epam.reportportal.auth.rules.exception.ErrorType; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.io.Serializable; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/CreateAuthIntegrationHandler.java b/src/main/java/com/epam/reportportal/auth/integration/handler/CreateAuthIntegrationHandler.java index 7a8374f0..f3bfb5b1 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/CreateAuthIntegrationHandler.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/CreateAuthIntegrationHandler.java @@ -16,11 +16,11 @@ package com.epam.reportportal.auth.integration.handler; +import com.epam.reportportal.auth.commons.ReportPortalUser; import com.epam.reportportal.auth.integration.AuthIntegrationType; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; /** * @author Ivan Budayeu diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationHandler.java b/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationHandler.java index abf95fb8..25a7e29f 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationHandler.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationHandler.java @@ -17,8 +17,8 @@ package com.epam.reportportal.auth.integration.handler; import com.epam.reportportal.auth.integration.AuthIntegrationType; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import java.util.Map; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationStrategy.java index f6761306..64b28fda 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/GetAuthIntegrationStrategy.java @@ -16,7 +16,7 @@ package com.epam.reportportal.auth.integration.handler; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; /** * @author Ivan Budayeu diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/CreateAuthIntegrationHandlerImpl.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/CreateAuthIntegrationHandlerImpl.java index 5c931d45..5c7818f7 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/CreateAuthIntegrationHandlerImpl.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/CreateAuthIntegrationHandlerImpl.java @@ -16,23 +16,23 @@ package com.epam.reportportal.auth.integration.handler.impl; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.converter.OAuthRegistrationConverters; import com.epam.reportportal.auth.integration.handler.CreateAuthIntegrationHandler; import com.epam.reportportal.auth.integration.handler.impl.strategy.AuthIntegrationStrategy; import com.epam.reportportal.auth.integration.provider.AuthIntegrationStrategyProvider; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import com.epam.reportportal.auth.oauth.OAuthProviderFactory; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import com.epam.reportportal.auth.store.MutableClientRegistrationRepository; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/DeleteAuthIntegrationHandlerImpl.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/DeleteAuthIntegrationHandlerImpl.java index 08e63698..ddd18ce5 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/DeleteAuthIntegrationHandlerImpl.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/DeleteAuthIntegrationHandlerImpl.java @@ -16,21 +16,21 @@ package com.epam.reportportal.auth.integration.handler.impl; -import static com.epam.ta.reportportal.commons.Predicates.equalTo; +import static com.epam.reportportal.auth.commons.Predicates.equalTo; +import com.epam.reportportal.auth.OperationCompletionRS; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.enums.IntegrationGroupEnum; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; import com.epam.reportportal.auth.event.SamlProvidersReloadEvent; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.handler.DeleteAuthIntegrationHandler; +import com.epam.reportportal.auth.rules.commons.validation.BusinessRule; +import com.epam.reportportal.auth.rules.commons.validation.Suppliers; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import com.epam.reportportal.auth.store.MutableClientRegistrationRepository; -import com.epam.reportportal.rules.commons.validation.BusinessRule; -import com.epam.reportportal.rules.commons.validation.Suppliers; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.enums.IntegrationGroupEnum; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.auth.OperationCompletionRS; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetActiveDirectoryStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetActiveDirectoryStrategy.java index 05e93758..8cc06dbc 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetActiveDirectoryStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetActiveDirectoryStrategy.java @@ -16,16 +16,16 @@ package com.epam.reportportal.auth.integration.handler.impl; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.converter.ActiveDirectoryConverter; import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationStrategy; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.ActiveDirectoryResource; +import com.epam.reportportal.auth.model.integration.auth.ActiveDirectoryResource; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetAuthIntegrationHandlerImpl.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetAuthIntegrationHandlerImpl.java index 0e77610a..7fe8fb59 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetAuthIntegrationHandlerImpl.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetAuthIntegrationHandlerImpl.java @@ -25,12 +25,12 @@ import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationHandler; import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationStrategy; import com.epam.reportportal.auth.model.ExtendedOAuthRegistrationResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.rules.commons.validation.Suppliers; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import com.epam.reportportal.auth.store.MutableClientRegistrationRepository; -import com.epam.reportportal.rules.commons.validation.Suppliers; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -80,8 +80,9 @@ public ResponseEntity getOauthIntegrationById(String .orElseGet(() -> { ExtendedOAuthRegistrationResource body = new ExtendedOAuthRegistrationResource(); body.setErrorCode(ErrorType.AUTH_INTEGRATION_NOT_FOUND.getCode()); - body.setMessage(Suppliers.formattedSupplier("Oauth settings with id = {} have not been found.", - oauthProviderId).get() + body.setMessage( + Suppliers.formattedSupplier("Oauth settings with id = {} have not been found.", + oauthProviderId).get() ); return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); }); diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetLdapStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetLdapStrategy.java index 82351b2a..2fa24d53 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetLdapStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetLdapStrategy.java @@ -16,17 +16,17 @@ package com.epam.reportportal.auth.integration.handler.impl; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.converter.LdapConverter; import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationStrategy; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.AbstractLdapResource; -import com.epam.reportportal.model.integration.auth.LdapResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractLdapResource; +import com.epam.reportportal.auth.model.integration.auth.LdapResource; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetSamlIntegrationsStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetSamlIntegrationsStrategy.java index aa9eea5c..e4dbdcf4 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetSamlIntegrationsStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/GetSamlIntegrationsStrategy.java @@ -2,16 +2,16 @@ import static com.epam.reportportal.auth.integration.converter.SamlConverter.TO_PROVIDERS_RESOURCE; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.handler.GetAuthIntegrationStrategy; import com.epam.reportportal.auth.model.SamlProvidersResource; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/ActiveDirectoryIntegrationStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/ActiveDirectoryIntegrationStrategy.java index 730cd4dc..1c799257 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/ActiveDirectoryIntegrationStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/ActiveDirectoryIntegrationStrategy.java @@ -18,12 +18,12 @@ import static com.epam.reportportal.auth.integration.converter.LdapConverter.UPDATE_FROM_REQUEST; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.validator.duplicate.IntegrationDuplicateValidator; import com.epam.reportportal.auth.integration.validator.request.AuthRequestValidator; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/AuthIntegrationStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/AuthIntegrationStrategy.java index dff666d5..6783ad5c 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/AuthIntegrationStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/AuthIntegrationStrategy.java @@ -16,18 +16,16 @@ package com.epam.reportportal.auth.integration.handler.impl.strategy; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; import com.epam.reportportal.auth.integration.builder.AuthIntegrationBuilder; import com.epam.reportportal.auth.integration.validator.duplicate.IntegrationDuplicateValidator; import com.epam.reportportal.auth.integration.validator.request.AuthRequestValidator; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; /** * @author Ihar Kahadouski diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/LdapIntegrationStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/LdapIntegrationStrategy.java index 9f577fa9..cfa8c751 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/LdapIntegrationStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/LdapIntegrationStrategy.java @@ -18,13 +18,13 @@ import static com.epam.reportportal.auth.integration.converter.LdapConverter.UPDATE_FROM_REQUEST; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.parameter.LdapParameter; import com.epam.reportportal.auth.integration.validator.duplicate.IntegrationDuplicateValidator; import com.epam.reportportal.auth.integration.validator.request.AuthRequestValidator; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; import org.jasypt.util.text.BasicTextEncryptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; diff --git a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/SamlIntegrationStrategy.java b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/SamlIntegrationStrategy.java index f50d27b5..3b0254b6 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/SamlIntegrationStrategy.java +++ b/src/main/java/com/epam/reportportal/auth/integration/handler/impl/strategy/SamlIntegrationStrategy.java @@ -23,17 +23,17 @@ import static com.epam.reportportal.auth.integration.parameter.SamlParameter.IDP_URL; import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; +import com.epam.reportportal.auth.entity.integration.IntegrationTypeDetails; import com.epam.reportportal.auth.event.SamlProvidersReloadEvent; import com.epam.reportportal.auth.integration.parameter.SamlParameter; import com.epam.reportportal.auth.integration.validator.duplicate.IntegrationDuplicateValidator; import com.epam.reportportal.auth.integration.validator.request.AuthRequestValidator; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.ta.reportportal.entity.integration.IntegrationTypeDetails; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.util.HashMap; import java.util.Map; import java.util.Objects; diff --git a/src/main/java/com/epam/reportportal/auth/integration/ldap/ActiveDirectoryAuthProvider.java b/src/main/java/com/epam/reportportal/auth/integration/ldap/ActiveDirectoryAuthProvider.java index aba83203..3dbd6072 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/ldap/ActiveDirectoryAuthProvider.java +++ b/src/main/java/com/epam/reportportal/auth/integration/ldap/ActiveDirectoryAuthProvider.java @@ -19,10 +19,10 @@ import static com.epam.reportportal.auth.integration.ldap.LdapAuthProvider.LDAP_TIMEOUT; import com.epam.reportportal.auth.EnableableAuthProvider; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.parameter.LdapParameter; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; import java.util.Collections; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.authentication.AuthenticationProvider; diff --git a/src/main/java/com/epam/reportportal/auth/integration/ldap/DetailsContextMapper.java b/src/main/java/com/epam/reportportal/auth/integration/ldap/DetailsContextMapper.java index d5d1cfa3..2bdb2afa 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/ldap/DetailsContextMapper.java +++ b/src/main/java/com/epam/reportportal/auth/integration/ldap/DetailsContextMapper.java @@ -16,8 +16,8 @@ package com.epam.reportportal.auth.integration.ldap; -import com.epam.ta.reportportal.commons.ReportPortalUser; -import com.epam.ta.reportportal.entity.user.User; +import com.epam.reportportal.auth.commons.ReportPortalUser; +import com.epam.reportportal.auth.entity.user.User; import java.util.Collection; import java.util.Map; import java.util.function.Supplier; diff --git a/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapAuthProvider.java b/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapAuthProvider.java index 6a899e82..bebc7b06 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapAuthProvider.java +++ b/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapAuthProvider.java @@ -19,14 +19,14 @@ import static java.util.Collections.singletonList; import com.epam.reportportal.auth.EnableableAuthProvider; +import com.epam.reportportal.auth.commons.accessible.Accessible; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.enums.FeatureFlag; +import com.epam.reportportal.auth.entity.integration.Integration; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.parameter.LdapParameter; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.ta.reportportal.commons.accessible.Accessible; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.enums.FeatureFlag; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.util.FeatureFlagHandler; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.epam.reportportal.auth.util.FeatureFlagHandler; import java.util.Collections; import org.jasypt.util.text.BasicTextEncryptor; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapUserReplicator.java b/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapUserReplicator.java index d41190f5..b613f595 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapUserReplicator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/ldap/LdapUserReplicator.java @@ -20,18 +20,18 @@ import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.Optional.ofNullable; +import com.epam.reportportal.auth.binary.UserBinaryDataService; +import com.epam.reportportal.auth.commons.ContentTypeResolver; +import com.epam.reportportal.auth.dao.ProjectRepository; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.user.User; +import com.epam.reportportal.auth.entity.user.UserRole; +import com.epam.reportportal.auth.entity.user.UserType; import com.epam.reportportal.auth.integration.AbstractUserReplicator; import com.epam.reportportal.auth.integration.parameter.LdapParameter; import com.epam.reportportal.auth.oauth.UserSynchronizationException; -import com.epam.reportportal.commons.ContentTypeResolver; -import com.epam.ta.reportportal.binary.UserBinaryDataService; -import com.epam.ta.reportportal.dao.ProjectRepository; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.project.Project; -import com.epam.ta.reportportal.entity.user.User; -import com.epam.ta.reportportal.entity.user.UserRole; -import com.epam.ta.reportportal.entity.user.UserType; -import com.epam.ta.reportportal.util.PersonalProjectService; +import com.epam.reportportal.auth.util.PersonalProjectService; import java.util.Map; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/com/epam/reportportal/auth/integration/parameter/LdapParameter.java b/src/main/java/com/epam/reportportal/auth/integration/parameter/LdapParameter.java index 16ce6333..4cd569f8 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/parameter/LdapParameter.java +++ b/src/main/java/com/epam/reportportal/auth/integration/parameter/LdapParameter.java @@ -16,14 +16,14 @@ package com.epam.reportportal.auth.integration.parameter; -import static com.epam.reportportal.rules.commons.validation.Suppliers.formattedSupplier; +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.formattedSupplier; import static java.util.Optional.ofNullable; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationParams; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationParams; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.util.HashMap; import java.util.Map; import java.util.Objects; diff --git a/src/main/java/com/epam/reportportal/auth/integration/parameter/ParameterUtils.java b/src/main/java/com/epam/reportportal/auth/integration/parameter/ParameterUtils.java index a82a0605..cbb804a1 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/parameter/ParameterUtils.java +++ b/src/main/java/com/epam/reportportal/auth/integration/parameter/ParameterUtils.java @@ -27,8 +27,8 @@ import static com.epam.reportportal.auth.integration.parameter.SamlParameter.LAST_NAME_ATTRIBUTE; import static com.epam.reportportal.auth.integration.parameter.SamlParameter.ROLES_ATTRIBUTE; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; @@ -46,14 +46,14 @@ public static void setLdapParameters(UpdateAuthRQ request, Integration integrati Arrays.stream(LdapParameter.values()).forEach(it -> it.setParameter(request, integration)); } - public static void setSamlParameters(UpdateAuthRQ request, Integration integration) { - IDP_NAME.setParameter(request, integration); - IDP_METADATA_URL.setParameter(request, integration); - EMAIL_ATTRIBUTE.setParameter(request, integration); - IDP_NAME_ID.setParameter(request, integration); - IDP_ALIAS.setParameter(request, integration); - IDP_URL.setParameter(request, integration); - ROLES_ATTRIBUTE.setParameter(request, integration); + public static void setSamlParameters(UpdateAuthRQ request, Integration integration) { + IDP_NAME.setParameter(request, integration); + IDP_METADATA_URL.setParameter(request, integration); + EMAIL_ATTRIBUTE.setParameter(request, integration); + IDP_NAME_ID.setParameter(request, integration); + IDP_ALIAS.setParameter(request, integration); + IDP_URL.setParameter(request, integration); + ROLES_ATTRIBUTE.setParameter(request, integration); FULL_NAME_ATTRIBUTE.getParameter(request).ifPresentOrElse(fullName -> { FIRST_NAME_ATTRIBUTE.removeParameter(integration); diff --git a/src/main/java/com/epam/reportportal/auth/integration/parameter/SamlParameter.java b/src/main/java/com/epam/reportportal/auth/integration/parameter/SamlParameter.java index d049a999..13cf9d04 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/parameter/SamlParameter.java +++ b/src/main/java/com/epam/reportportal/auth/integration/parameter/SamlParameter.java @@ -16,14 +16,14 @@ package com.epam.reportportal.auth.integration.parameter; -import static com.epam.reportportal.rules.commons.validation.Suppliers.formattedSupplier; +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.formattedSupplier; import static java.util.Optional.ofNullable; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationParams; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationParams; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -35,17 +35,17 @@ */ public enum SamlParameter { - BASE_PATH("callbackUrl", false), - IDP_NAME("identityProviderName", true), - IDP_METADATA_URL("identityProviderMetadataUrl", true), - EMAIL_ATTRIBUTE("emailAttribute", true), - IDP_NAME_ID("identityProviderNameId", false), - IDP_ALIAS("identityProviderAlias", false), - IDP_URL("identityProviderUrl", false), - FULL_NAME_ATTRIBUTE("fullNameAttribute", false), - FIRST_NAME_ATTRIBUTE("firstNameAttribute", false), - LAST_NAME_ATTRIBUTE("lastNameAttribute", false), - ROLES_ATTRIBUTE("rolesAttribute", false); + BASE_PATH("callbackUrl", false), + IDP_NAME("identityProviderName", true), + IDP_METADATA_URL("identityProviderMetadataUrl", true), + EMAIL_ATTRIBUTE("emailAttribute", true), + IDP_NAME_ID("identityProviderNameId", false), + IDP_ALIAS("identityProviderAlias", false), + IDP_URL("identityProviderUrl", false), + FULL_NAME_ATTRIBUTE("fullNameAttribute", false), + FIRST_NAME_ATTRIBUTE("firstNameAttribute", false), + LAST_NAME_ATTRIBUTE("lastNameAttribute", false), + ROLES_ATTRIBUTE("rolesAttribute", false); private String parameterName; diff --git a/src/main/java/com/epam/reportportal/auth/integration/saml/Attribute.java b/src/main/java/com/epam/reportportal/auth/integration/saml/Attribute.java index 4763d491..80f3d35d 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/saml/Attribute.java +++ b/src/main/java/com/epam/reportportal/auth/integration/saml/Attribute.java @@ -19,7 +19,6 @@ import java.io.Serializable; import java.util.LinkedList; import java.util.List; -import java.util.Objects; import lombok.EqualsAndHashCode; import lombok.Getter; import org.springframework.security.saml.saml2.attribute.AttributeNameFormat; diff --git a/src/main/java/com/epam/reportportal/auth/integration/saml/ReportPortalSamlAuthenticationManager.java b/src/main/java/com/epam/reportportal/auth/integration/saml/ReportPortalSamlAuthenticationManager.java index 1d303e82..d54ff00e 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/saml/ReportPortalSamlAuthenticationManager.java +++ b/src/main/java/com/epam/reportportal/auth/integration/saml/ReportPortalSamlAuthenticationManager.java @@ -16,8 +16,8 @@ package com.epam.reportportal.auth.integration.saml; +import com.epam.reportportal.auth.entity.user.User; import com.epam.reportportal.auth.util.AuthUtils; -import com.epam.ta.reportportal.entity.user.User; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; diff --git a/src/main/java/com/epam/reportportal/auth/integration/saml/SamlUserReplicator.java b/src/main/java/com/epam/reportportal/auth/integration/saml/SamlUserReplicator.java index 47791f1f..e7bab690 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/saml/SamlUserReplicator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/saml/SamlUserReplicator.java @@ -19,27 +19,27 @@ import static com.epam.reportportal.auth.util.AuthUtils.CROP_DOMAIN; import static com.epam.reportportal.auth.util.AuthUtils.NORMALIZE_STRING; +import com.epam.reportportal.auth.binary.UserBinaryDataService; +import com.epam.reportportal.auth.commons.ContentTypeResolver; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.dao.IntegrationTypeRepository; +import com.epam.reportportal.auth.dao.ProjectRepository; +import com.epam.reportportal.auth.dao.UserRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.IntegrationType; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.user.User; +import com.epam.reportportal.auth.entity.user.UserRole; +import com.epam.reportportal.auth.entity.user.UserType; import com.epam.reportportal.auth.event.activity.AssignUserEvent; import com.epam.reportportal.auth.event.activity.ProjectCreatedEvent; import com.epam.reportportal.auth.event.activity.UserCreatedEvent; import com.epam.reportportal.auth.integration.AbstractUserReplicator; import com.epam.reportportal.auth.integration.AuthIntegrationType; import com.epam.reportportal.auth.integration.parameter.SamlParameter; -import com.epam.reportportal.commons.ContentTypeResolver; -import com.epam.ta.reportportal.binary.UserBinaryDataService; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.dao.IntegrationTypeRepository; -import com.epam.ta.reportportal.dao.ProjectRepository; -import com.epam.ta.reportportal.dao.UserRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.ta.reportportal.entity.integration.IntegrationType; -import com.epam.ta.reportportal.entity.project.Project; -import com.epam.ta.reportportal.entity.user.User; -import com.epam.ta.reportportal.entity.user.UserRole; -import com.epam.ta.reportportal.entity.user.UserType; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.ta.reportportal.util.PersonalProjectService; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.epam.reportportal.auth.util.PersonalProjectService; import java.util.List; import java.util.Objects; import java.util.Optional; diff --git a/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/IntegrationDuplicateValidator.java b/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/IntegrationDuplicateValidator.java index 021f33cc..f63771be 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/IntegrationDuplicateValidator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/IntegrationDuplicateValidator.java @@ -16,7 +16,7 @@ package com.epam.reportportal.auth.integration.validator.duplicate; -import com.epam.ta.reportportal.entity.integration.Integration; +import com.epam.reportportal.auth.entity.integration.Integration; public interface IntegrationDuplicateValidator { diff --git a/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/UniqueNameGlobalIntegrationValidator.java b/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/UniqueNameGlobalIntegrationValidator.java index ce246365..d64f6c3a 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/UniqueNameGlobalIntegrationValidator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/validator/duplicate/UniqueNameGlobalIntegrationValidator.java @@ -16,10 +16,10 @@ package com.epam.reportportal.auth.integration.validator.duplicate; -import com.epam.reportportal.rules.commons.validation.BusinessRule; -import com.epam.ta.reportportal.dao.IntegrationRepository; -import com.epam.ta.reportportal.entity.integration.Integration; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.dao.IntegrationRepository; +import com.epam.reportportal.auth.entity.integration.Integration; +import com.epam.reportportal.auth.rules.commons.validation.BusinessRule; +import com.epam.reportportal.auth.rules.exception.ErrorType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/epam/reportportal/auth/integration/validator/request/SamlUpdateAuthRequestValidator.java b/src/main/java/com/epam/reportportal/auth/integration/validator/request/SamlUpdateAuthRequestValidator.java index b64728ba..b2d0c016 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/validator/request/SamlUpdateAuthRequestValidator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/validator/request/SamlUpdateAuthRequestValidator.java @@ -16,15 +16,15 @@ package com.epam.reportportal.auth.integration.validator.request; +import static com.epam.reportportal.auth.commons.Predicates.equalTo; import static com.epam.reportportal.auth.integration.parameter.SamlParameter.FIRST_NAME_ATTRIBUTE; import static com.epam.reportportal.auth.integration.parameter.SamlParameter.FULL_NAME_ATTRIBUTE; import static com.epam.reportportal.auth.integration.parameter.SamlParameter.LAST_NAME_ATTRIBUTE; -import static com.epam.ta.reportportal.commons.Predicates.equalTo; import com.epam.reportportal.auth.integration.validator.request.param.provider.ParamNamesProvider; -import com.epam.reportportal.rules.commons.validation.BusinessRule; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.commons.validation.BusinessRule; +import com.epam.reportportal.auth.rules.exception.ErrorType; import java.util.function.Predicate; public class SamlUpdateAuthRequestValidator extends UpdateAuthRequestValidator { diff --git a/src/main/java/com/epam/reportportal/auth/integration/validator/request/UpdateAuthRequestValidator.java b/src/main/java/com/epam/reportportal/auth/integration/validator/request/UpdateAuthRequestValidator.java index aa5381b0..96b07606 100644 --- a/src/main/java/com/epam/reportportal/auth/integration/validator/request/UpdateAuthRequestValidator.java +++ b/src/main/java/com/epam/reportportal/auth/integration/validator/request/UpdateAuthRequestValidator.java @@ -16,13 +16,13 @@ package com.epam.reportportal.auth.integration.validator.request; -import static com.epam.reportportal.rules.commons.validation.BusinessRule.expect; -import static com.epam.reportportal.rules.commons.validation.Suppliers.formattedSupplier; +import static com.epam.reportportal.auth.rules.commons.validation.BusinessRule.expect; +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.formattedSupplier; import static java.util.Optional.ofNullable; import com.epam.reportportal.auth.integration.validator.request.param.provider.ParamNamesProvider; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.model.integration.auth.UpdateAuthRQ; +import com.epam.reportportal.auth.rules.exception.ErrorType; import java.util.List; import java.util.Optional; import org.apache.commons.lang3.StringUtils; diff --git a/src/main/java/com/epam/reportportal/auth/model/ExtendedOAuthRegistrationResource.java b/src/main/java/com/epam/reportportal/auth/model/ExtendedOAuthRegistrationResource.java index 995d047f..09d941ae 100644 --- a/src/main/java/com/epam/reportportal/auth/model/ExtendedOAuthRegistrationResource.java +++ b/src/main/java/com/epam/reportportal/auth/model/ExtendedOAuthRegistrationResource.java @@ -15,7 +15,7 @@ */ package com.epam.reportportal.auth.model; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; import lombok.Data; import lombok.EqualsAndHashCode; diff --git a/src/main/java/com/epam/reportportal/auth/model/SamlProvidersResource.java b/src/main/java/com/epam/reportportal/auth/model/SamlProvidersResource.java index 3851a9f5..0215f410 100644 --- a/src/main/java/com/epam/reportportal/auth/model/SamlProvidersResource.java +++ b/src/main/java/com/epam/reportportal/auth/model/SamlProvidersResource.java @@ -16,18 +16,18 @@ package com.epam.reportportal.auth.model; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; +import javax.validation.Valid; import lombok.Getter; import lombok.Setter; -import javax.validation.Valid; -import java.util.List; - @Setter @Getter @JsonInclude(JsonInclude.Include.NON_NULL) public class SamlProvidersResource extends AbstractAuthResource { - @Valid - private List providers; + + @Valid + private List providers; } diff --git a/src/main/java/com/epam/reportportal/auth/model/SamlResource.java b/src/main/java/com/epam/reportportal/auth/model/SamlResource.java index 24154b55..3576e741 100644 --- a/src/main/java/com/epam/reportportal/auth/model/SamlResource.java +++ b/src/main/java/com/epam/reportportal/auth/model/SamlResource.java @@ -16,15 +16,14 @@ package com.epam.reportportal.auth.model; -import com.epam.reportportal.model.integration.auth.AbstractAuthResource; +import com.epam.reportportal.auth.model.integration.auth.AbstractAuthResource; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.NotEmpty; import lombok.Getter; import lombok.Setter; -import javax.validation.constraints.NotEmpty; - /** * @author Ihar Kahadouski */ @@ -35,57 +34,57 @@ @JsonInclude(JsonInclude.Include.NON_NULL) public class SamlResource extends AbstractAuthResource { - private Long id; + private Long id; - @JsonProperty(value = "callbackUrl") - private String callbackUrl; + @JsonProperty(value = "callbackUrl") + private String callbackUrl; - /** - * Provider name associated with IDP - */ - @NotEmpty - private String identityProviderName; - /** - * Alias associated with IDP - */ - private String identityProviderAlias; - /** - * IDP metadata URL - */ - @NotEmpty - private String identityProviderMetadataUrl; - /** - * Attribute Name Format Id associated with IDP for user identification - */ - private String identityProviderNameId; - /** - * IDP URL - */ - private String identityProviderUrl; - /** - * Attribute name associated with full name of user in SAML response - */ - private String fullNameAttribute; - /** - * Attribute name associated with first name of user in SAML response - */ - private String firstNameAttribute; - /** - * Attribute name associated with last name of user in SAML response - */ - private String lastNameAttribute; - /** - * Attribute name associated with email of user in SAML response - */ - @NotEmpty - private String emailAttribute; - /** - * Attribute name associated with roles of user in SAML response - */ - private String rolesAttribute; - /** - * Indicates IDP availability for authentication - */ - private boolean enabled; + /** + * Provider name associated with IDP + */ + @NotEmpty + private String identityProviderName; + /** + * Alias associated with IDP + */ + private String identityProviderAlias; + /** + * IDP metadata URL + */ + @NotEmpty + private String identityProviderMetadataUrl; + /** + * Attribute Name Format Id associated with IDP for user identification + */ + private String identityProviderNameId; + /** + * IDP URL + */ + private String identityProviderUrl; + /** + * Attribute name associated with full name of user in SAML response + */ + private String fullNameAttribute; + /** + * Attribute name associated with first name of user in SAML response + */ + private String firstNameAttribute; + /** + * Attribute name associated with last name of user in SAML response + */ + private String lastNameAttribute; + /** + * Attribute name associated with email of user in SAML response + */ + @NotEmpty + private String emailAttribute; + /** + * Attribute name associated with roles of user in SAML response + */ + private String rolesAttribute; + /** + * Indicates IDP availability for authentication + */ + private boolean enabled; -} \ No newline at end of file +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/AbstractAuthResource.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/AbstractAuthResource.java new file mode 100644 index 00000000..f5a353e4 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/AbstractAuthResource.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.io.Serializable; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ihar Kahadouski + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AbstractAuthResource implements Serializable { + + private String type; + +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/AbstractLdapResource.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/AbstractLdapResource.java new file mode 100644 index 00000000..f8ff1066 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/AbstractLdapResource.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import javax.validation.Valid; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ivan Budayeu + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public abstract class AbstractLdapResource extends AbstractAuthResource { + + @JsonProperty(value = "id") + private Long id; + + @Valid + @JsonProperty(value = "ldapAttributes") + private LdapAttributes ldapAttributes; + + @Override + public String toString() { + return "AbstractLdapResource{" + "id=" + id + ", ldapAttributes=" + ldapAttributes + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/ActiveDirectoryResource.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/ActiveDirectoryResource.java new file mode 100644 index 00000000..d338df49 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/ActiveDirectoryResource.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ivan Budayeu + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ActiveDirectoryResource extends AbstractLdapResource { + + @JsonProperty(value = "domain") + private String domain; + + @JsonProperty(value = "searchFilter") + private String searchFilter; + + @Override + public String toString() { + return "ActiveDirectoryResource{" + "domain='" + domain + '\'' + ", searchFilter='" + + searchFilter + '\'' + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/LdapAttributes.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/LdapAttributes.java new file mode 100644 index 00000000..f5d500aa --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/LdapAttributes.java @@ -0,0 +1,61 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ivan Budayeu + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class LdapAttributes implements Serializable { + + @NotNull + @JsonProperty(value = "enabled") + private Boolean enabled; + + @NotBlank + @Pattern(regexp = "^ldaps?://.*") + @JsonProperty(value = "url") + private String url; + + @NotBlank + @JsonProperty(value = "baseDn") + private String baseDn; + + @NotNull + @Valid + @JsonProperty("synchronizationAttributes") + private SynchronizationAttributesResource synchronizationAttributes; + + @Override + public String toString() { + return "LdapAttributes{" + "enabled=" + enabled + ", url='" + url + '\'' + ", baseDn='" + baseDn + + '\'' + + ", synchronizationAttributes=" + synchronizationAttributes + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/LdapResource.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/LdapResource.java new file mode 100644 index 00000000..54e69fae --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/LdapResource.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ivan Budayeu + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class LdapResource extends AbstractLdapResource { + + @JsonProperty(value = "userDnPattern") + private String userDnPattern; + + @JsonProperty(value = "userSearchFilter") + private String userSearchFilter; + + @JsonProperty(value = "groupSearchBase") + private String groupSearchBase; + + @JsonProperty(value = "groupSearchFilter") + private String groupSearchFilter; + + @JsonProperty(value = "passwordEncoderType") + private String passwordEncoderType; + + @JsonProperty(value = "passwordAttribute") + private String passwordAttribute; + + @JsonProperty(value = "managerDn") + private String managerDn; + + @Override + public String toString() { + return "LdapResource{" + "userDnPattern='" + userDnPattern + '\'' + ", userSearchFilter='" + + userSearchFilter + '\'' + + ", groupSearchBase='" + groupSearchBase + '\'' + ", groupSearchFilter='" + + groupSearchFilter + '\'' + + ", passwordEncoderType='" + passwordEncoderType + '\'' + ", passwordAttribute='" + + passwordAttribute + '\'' + + ", managerDn='" + managerDn + '\'' + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/SynchronizationAttributesResource.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/SynchronizationAttributesResource.java new file mode 100644 index 00000000..5127bf73 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/SynchronizationAttributesResource.java @@ -0,0 +1,60 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ivan Budayeu + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SynchronizationAttributesResource implements Serializable { + + @NotBlank + @JsonProperty(value = "email") + private String email; + + @JsonProperty(value = "fullName") + private String fullName; + + @JsonProperty(value = "firstName") + private String firstName; + + @JsonProperty(value = "lastName") + private String lastName; + + @JsonProperty(value = "photo") + private String photo; + + @Override + public String toString() { + return "SynchronizationAttributesResource{" + + "email='" + email + '\'' + + ", fullName='" + fullName + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", photo='" + photo + '\'' + + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/model/integration/auth/UpdateAuthRQ.java b/src/main/java/com/epam/reportportal/auth/model/integration/auth/UpdateAuthRQ.java new file mode 100644 index 00000000..1cd3173d --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/integration/auth/UpdateAuthRQ.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.integration.auth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +/** + * @author Ihar Kahadouski + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class UpdateAuthRQ { + + @NotNull + private Boolean enabled; + + @NotEmpty + @JsonProperty("integrationParameters") + private Map integrationParams; + + @Override + public String toString() { + return "UpdateAuthRQ{" + "enabled=" + enabled + ", authParams=" + integrationParams + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/model/settings/OAuthRegistrationResource.java b/src/main/java/com/epam/reportportal/auth/model/settings/OAuthRegistrationResource.java new file mode 100644 index 00000000..1e71fae9 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/model/settings/OAuthRegistrationResource.java @@ -0,0 +1,171 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.model.settings; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.Map; +import java.util.Set; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Getter; +import lombok.Setter; + +/** + * Settings for OAuth provider registration. + * + * @author Anton Machulski + */ +@Setter +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class OAuthRegistrationResource implements Serializable { + + public static final String URL_PATTERN = "^(http://|https://)?(www\\.)?([a-zA-Z0-9-]+)(\\.[a-zA-Z0-9-]+)*(:[0-9]+)?(/[a-z_-]+)*$"; + + @JsonProperty(value = "id") + private String id; + + @NotBlank + @JsonProperty(value = "clientId") + private String clientId; + + @NotBlank + @JsonProperty(value = "clientSecret") + private String clientSecret; + + @JsonProperty(value = "clientAuthMethod") + private String clientAuthMethod; + + @JsonProperty(value = "authGrantType") + private String authGrantType; + + @JsonProperty(value = "redirectUrlTemplate") + private String redirectUrlTemplate; + + @Pattern(regexp = URL_PATTERN) + @JsonProperty(value = "authorizationUri") + @Schema(type = "string", pattern = URL_PATTERN, example = "string") + private String authorizationUri; + + @Pattern(regexp = URL_PATTERN) + @JsonProperty(value = "tokenUri") + @Schema(type = "string", pattern = URL_PATTERN, example = "string") + private String tokenUri; + + @JsonProperty(value = "userInfoEndpointUri") + private String userInfoEndpointUri; + + @JsonProperty(value = "userInfoEndpointNameAttribute") + private String userInfoEndpointNameAttribute; + + @JsonProperty(value = "jwkSetUri") + private String jwkSetUri; + + @JsonProperty(value = "clientName") + private String clientName; + + @JsonProperty(value = "scopes") + private Set scopes; + + @JsonProperty(value = "restrictions") + private Map restrictions; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + OAuthRegistrationResource that = (OAuthRegistrationResource) o; + + if (id != null ? !id.equals(that.id) : that.id != null) { + return false; + } + if (clientId != null ? !clientId.equals(that.clientId) : that.clientId != null) { + return false; + } + if (clientSecret != null ? !clientSecret.equals(that.clientSecret) + : that.clientSecret != null) { + return false; + } + if (clientAuthMethod != null ? !clientAuthMethod.equals(that.clientAuthMethod) + : that.clientAuthMethod != null) { + return false; + } + if (authGrantType != null ? !authGrantType.equals(that.authGrantType) + : that.authGrantType != null) { + return false; + } + if (redirectUrlTemplate != null ? !redirectUrlTemplate.equals(that.redirectUrlTemplate) + : that.redirectUrlTemplate != null) { + return false; + } + if (authorizationUri != null ? !authorizationUri.equals(that.authorizationUri) + : that.authorizationUri != null) { + return false; + } + if (tokenUri != null ? !tokenUri.equals(that.tokenUri) : that.tokenUri != null) { + return false; + } + if (userInfoEndpointUri != null ? !userInfoEndpointUri.equals(that.userInfoEndpointUri) + : that.userInfoEndpointUri != null) { + return false; + } + if (userInfoEndpointNameAttribute != null ? + !userInfoEndpointNameAttribute.equals(that.userInfoEndpointNameAttribute) : + that.userInfoEndpointNameAttribute != null) { + return false; + } + if (jwkSetUri != null ? !jwkSetUri.equals(that.jwkSetUri) : that.jwkSetUri != null) { + return false; + } + if (clientName != null ? !clientName.equals(that.clientName) : that.clientName != null) { + return false; + } + if (scopes != null ? !scopes.equals(that.scopes) : that.scopes != null) { + return false; + } + return restrictions != null ? restrictions.equals(that.restrictions) + : that.restrictions == null; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (clientId != null ? clientId.hashCode() : 0); + result = 31 * result + (clientSecret != null ? clientSecret.hashCode() : 0); + result = 31 * result + (clientAuthMethod != null ? clientAuthMethod.hashCode() : 0); + result = 31 * result + (authGrantType != null ? authGrantType.hashCode() : 0); + result = 31 * result + (redirectUrlTemplate != null ? redirectUrlTemplate.hashCode() : 0); + result = 31 * result + (authorizationUri != null ? authorizationUri.hashCode() : 0); + result = 31 * result + (tokenUri != null ? tokenUri.hashCode() : 0); + result = 31 * result + (userInfoEndpointUri != null ? userInfoEndpointUri.hashCode() : 0); + result = 31 * result + (userInfoEndpointNameAttribute != null + ? userInfoEndpointNameAttribute.hashCode() : 0); + result = 31 * result + (jwkSetUri != null ? jwkSetUri.hashCode() : 0); + result = 31 * result + (clientName != null ? clientName.hashCode() : 0); + result = 31 * result + (scopes != null ? scopes.hashCode() : 0); + result = 31 * result + (restrictions != null ? restrictions.hashCode() : 0); + return result; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/oauth/OAuthProviderFactory.java b/src/main/java/com/epam/reportportal/auth/oauth/OAuthProviderFactory.java index 176d3b1f..db3b7a45 100644 --- a/src/main/java/com/epam/reportportal/auth/oauth/OAuthProviderFactory.java +++ b/src/main/java/com/epam/reportportal/auth/oauth/OAuthProviderFactory.java @@ -18,10 +18,10 @@ import static com.epam.reportportal.auth.integration.converter.OAuthRegistrationConverters.FROM_SPRING_MERGE; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.reportportal.rules.exception.ErrorType; -import com.epam.reportportal.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; +import com.epam.reportportal.auth.model.settings.OAuthRegistrationResource; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import org.springframework.security.config.oauth2.client.CommonOAuth2Provider; import org.springframework.security.oauth2.client.registration.ClientRegistration; diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/ExceptionMappings.java b/src/main/java/com/epam/reportportal/auth/rules/commons/ExceptionMappings.java new file mode 100644 index 00000000..d33ed6bd --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/ExceptionMappings.java @@ -0,0 +1,84 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons; + +import com.epam.reportportal.auth.rules.commons.exception.message.ArgumentNotValidMessageBuilder; +import com.epam.reportportal.auth.rules.commons.exception.message.DefaultExceptionMessageBuilder; +import com.epam.reportportal.auth.rules.commons.exception.message.ExceptionMessageBuilder; +import com.epam.reportportal.auth.rules.commons.exception.rest.RestErrorDefinition; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.LockedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.multipart.support.MissingServletRequestPartException; + +/** + * Set of default exception mappings. + * + * @author Andrei Varabyeu + */ +public final class ExceptionMappings { + + private static final ReloadableResourceBundleMessageSource MESSAGE_SOURCE = + new ReloadableResourceBundleMessageSource() { + { + setBasename("classpath:ValidationMessages"); + setDefaultEncoding("UTF-8"); + } + }; + + private static final ExceptionMessageBuilder DEFAULT_MESSAGE_BUILDER = + new DefaultExceptionMessageBuilder(); + + public static Map, RestErrorDefinition> DEFAULT_MAPPING = ImmutableMap + ., RestErrorDefinition>builder() + .put(MethodArgumentNotValidException.class, + new RestErrorDefinition<>(400, ErrorType.INCORRECT_REQUEST, + new ArgumentNotValidMessageBuilder(MESSAGE_SOURCE))) + + .put(HttpMessageNotReadableException.class, + new RestErrorDefinition<>(400, ErrorType.INCORRECT_REQUEST, DEFAULT_MESSAGE_BUILDER)) + .put(MissingServletRequestPartException.class, + new RestErrorDefinition<>(400, ErrorType.INCORRECT_REQUEST, DEFAULT_MESSAGE_BUILDER)) + .put(MissingServletRequestParameterException.class, + new RestErrorDefinition<>(400, ErrorType.INCORRECT_REQUEST, DEFAULT_MESSAGE_BUILDER)) + .put(AccessDeniedException.class, + new RestErrorDefinition<>(403, ErrorType.ACCESS_DENIED, DEFAULT_MESSAGE_BUILDER)) + .put(BadCredentialsException.class, + new RestErrorDefinition<>(401, ErrorType.ACCESS_DENIED, DEFAULT_MESSAGE_BUILDER)) + .put(LockedException.class, + new RestErrorDefinition<>(403, ErrorType.ADDRESS_LOCKED, DEFAULT_MESSAGE_BUILDER)) + .put(ReportPortalException.class, + new RestErrorDefinition<>(500, ErrorType.UNCLASSIFIED_REPORT_PORTAL_ERROR, + DEFAULT_MESSAGE_BUILDER)) + + .put(RestClientException.class, + new RestErrorDefinition<>(400, ErrorType.UNABLE_INTERACT_WITH_INTEGRATION, + DEFAULT_MESSAGE_BUILDER)) + + .put(Throwable.class, + new RestErrorDefinition<>(500, ErrorType.UNCLASSIFIED_ERROR, DEFAULT_MESSAGE_BUILDER)) + .build(); +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/forwarding/ForwardingClientExceptionHandler.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/forwarding/ForwardingClientExceptionHandler.java new file mode 100644 index 00000000..3d2446ca --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/forwarding/ForwardingClientExceptionHandler.java @@ -0,0 +1,36 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.forwarding; + +import java.io.IOException; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.DefaultResponseErrorHandler; + +/** + * Exception handler for Spring RestTemplate. Throws exception with downstream service response to + * be forwarded to upstream service (just propagates exception to upstream service) + * + * @author Andrei Varabyeu + */ +public class ForwardingClientExceptionHandler extends DefaultResponseErrorHandler { + + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + throw new ResponseForwardingException(response); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/forwarding/ResponseForwardingException.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/forwarding/ResponseForwardingException.java new file mode 100644 index 00000000..7b0968b5 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/forwarding/ResponseForwardingException.java @@ -0,0 +1,60 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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. + */ +/* + * This file is part of Report Portal. + * + * Report Portal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Report Portal is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Report Portal. If not, see . + */ + +package com.epam.reportportal.auth.rules.commons.exception.forwarding; + +import com.google.common.io.ByteStreams; +import java.io.IOException; +import lombok.Getter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; + +/** + * Exception to be forwarded from downstream to upstream microservice. + * + * @author Andrei Varabyeu + */ +@Getter +public class ResponseForwardingException extends RuntimeException { + + private final byte[] body; + private final HttpHeaders headers; + private final HttpStatus status; + + public ResponseForwardingException(ClientHttpResponse response) throws IOException { + this.headers = response.getHeaders(); + this.status = response.getStatusCode(); + this.body = ByteStreams.toByteArray(response.getBody()); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/ArgumentNotValidMessageBuilder.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/ArgumentNotValidMessageBuilder.java new file mode 100644 index 00000000..41b29c49 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/ArgumentNotValidMessageBuilder.java @@ -0,0 +1,53 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.message; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; + +/** + * {@link MethodArgumentNotValidException} message builder + * + * @author Andrei Varabyeu + */ +@Setter +@Getter +public class ArgumentNotValidMessageBuilder implements + ExceptionMessageBuilder { + + private ReloadableResourceBundleMessageSource messageSource; + + public ArgumentNotValidMessageBuilder(ReloadableResourceBundleMessageSource messageSource) { + this.messageSource = messageSource; + } + + @Override + public String buildMessage(MethodArgumentNotValidException e) { + StringBuilder sb = new StringBuilder(); + for (ObjectError error : e.getBindingResult().getAllErrors()) { + sb.append("[").append(messageSource.getMessage(error, LocaleContextHolder.getLocale())) + .append("] "); + } + return sb.toString(); + } + + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/DefaultExceptionMessageBuilder.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/DefaultExceptionMessageBuilder.java new file mode 100644 index 00000000..095ab277 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/DefaultExceptionMessageBuilder.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.message; + +/** + * Default exception builder. Just reads the exception message + * + * @author Andrei Varabyeu + */ +public class DefaultExceptionMessageBuilder implements ExceptionMessageBuilder { + + @Override + public String buildMessage(Exception e) { + return e.getMessage(); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/ExceptionMessageBuilder.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/ExceptionMessageBuilder.java new file mode 100644 index 00000000..57e9ccea --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/message/ExceptionMessageBuilder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.message; + +/** + * Builds custom exception strings from Exception. Lots of exceptions have custom data which should + * be showed to clients in custom way + * + * @author Andrei Varabyeu + */ +public interface ExceptionMessageBuilder { + + /** + * Builds message string from provided exception + * + * @param e Exception message should be built from + * @return Built message + */ + String buildMessage(T e); +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/DefaultErrorResolver.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/DefaultErrorResolver.java new file mode 100644 index 00000000..9a05f74c --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/DefaultErrorResolver.java @@ -0,0 +1,125 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.formattedMessage; +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.formattedSupplier; + +import com.google.common.base.Preconditions; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Default implementation of ErrorResolver. + * + * @author Andrei Varabyeu + */ +public class DefaultErrorResolver implements ErrorResolver { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultErrorResolver.class); + + private final Map, RestErrorDefinition> exceptionMappingDefinitions; + + public DefaultErrorResolver( + Map, RestErrorDefinition> exceptionMappingDefinitions) { + Preconditions + .checkNotNull(exceptionMappingDefinitions, "Exceptions mappings should't be null"); + this.exceptionMappingDefinitions = exceptionMappingDefinitions; + } + + + @Override + public RestError resolveError(Exception ex) { + RestErrorDefinition errorDefinition = getRestErrorDefinition(ex); + if (null == errorDefinition) { + return null; + } + + LOGGER.error(ex.getMessage(), ex); + + RestError.Builder errorBuilder = new RestError.Builder(); + String message; + if (formattedMessage(errorDefinition.getError().getDescription())) { + message = formattedSupplier(errorDefinition.getError().getDescription(), + errorDefinition.getExceptionMessage(ex)).get(); + } else { + message = new StringBuilder(errorDefinition.getError().getDescription()).append(" [") + .append(errorDefinition.getExceptionMessage(ex)).append("]").toString(); + } + errorBuilder.setError(errorDefinition.getError()) + .setMessage(message) + .setStatus(errorDefinition.getHttpStatus()); + + return errorBuilder.build(); + + } + + /** + * Returns the config-time 'template' RestErrorDefinition instance configured for the specified + * Exception, or {@code null} if a match was not found. + *

+ * The config-time template is used as the basis for the RestError constructed at runtime. + * + * @param ex Exception to be resolved + * @return the template to use for the RestError instance to be constructed. + */ + private RestErrorDefinition getRestErrorDefinition(Exception ex) { + Map, RestErrorDefinition> mappings = this.exceptionMappingDefinitions; + if (mappings.isEmpty()) { + return null; + } + RestErrorDefinition template = null; + int deepest = Integer.MAX_VALUE; + for (Map.Entry, RestErrorDefinition> entry : mappings.entrySet()) { + Class key = entry.getKey(); + int depth = getDepth(key, ex); + if (depth >= 0 && depth < deepest) { + deepest = depth; + template = entry.getValue(); + } + } + return template; + } + + /** + * Return the depth to the superclass matching. + * + * @param exceptionMapping Possible exception match + * @param ex Exception to be checked + * @return 0 means ex matches exactly. Returns -1 if there's no match. Otherwise, returns depth. + * Lowest depth wins. + */ + protected int getDepth(Class exceptionMapping, Exception ex) { + return getDepth(exceptionMapping, ex.getClass(), 0); + } + + private int getDepth(Class exceptionMapping, Class exceptionClass, + int depth) { + if (exceptionClass.equals(exceptionMapping)) { + // Found it! + return depth; + } + // If we've gone as far as we can go and haven't found it... + if (exceptionClass.equals(Throwable.class)) { + return -1; + } + return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/ErrorResolver.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/ErrorResolver.java new file mode 100644 index 00000000..65fbb894 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/ErrorResolver.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +/** + * Custom exception resolver. Creates {@link RestError} + * + * @author Andrei Varabyeu + */ +public interface ErrorResolver { + + /** + * Create RestError from provided exception. + * + * @param ex Exception to be resolved + * @return Resolved {@link RestError} + */ + RestError resolveError(Exception ex); +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/ReportPortalExceptionResolver.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/ReportPortalExceptionResolver.java new file mode 100644 index 00000000..c32718dd --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/ReportPortalExceptionResolver.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; + +/** + * Resolver for ReportPortal Exceptions. + * + * @author Andrei Varabyeu + */ +public class ReportPortalExceptionResolver implements ErrorResolver { + + private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalExceptionResolver.class); + + private final ErrorResolver defaultErrorResolver; + + public ReportPortalExceptionResolver(ErrorResolver defaultErrorResolver) { + this.defaultErrorResolver = defaultErrorResolver; + } + + @Override + public RestError resolveError(Exception ex) { + + LOGGER.error("ReportPortalExceptionResolver > {}", ex.getMessage(), ex); + + if (ReportPortalException.class.isAssignableFrom(ex.getClass())) { + ReportPortalException currentException = (ReportPortalException) ex; + RestError.Builder builder = new RestError.Builder(); + builder.setMessage(currentException.getMessage()) + // .setStackTrace(errors.toString()) + .setStatus(StatusCodeMapping.getHttpStatus(currentException.getErrorType(), + HttpStatus.INTERNAL_SERVER_ERROR)) + .setError(currentException.getErrorType()); + + return builder.build(); + } else { + return defaultErrorResolver.resolveError(ex); + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestError.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestError.java new file mode 100644 index 00000000..9f988270 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestError.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +import com.epam.reportportal.auth.rules.exception.ErrorRS; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +/** + * Rest Error representation. Contains rest error template and real exception data. + * + * @author Andrei Varabyeu + */ +@Getter +public class RestError { + + private final ErrorRS errorRs; + + /** + * HTTP Status + */ + private final HttpStatus httpStatus; + + public RestError(HttpStatus httpStatus, ErrorRS errorRs) { + this.httpStatus = httpStatus; + this.errorRs = errorRs; + } + + /** + * Builder for Rest Error. + * + * @author Andrei Varabyeu + */ + public static class Builder { + + private HttpStatus status; + private ErrorType error; + private String message; + private String stackTrace; + + public Builder setStatus(HttpStatus status) { + this.status = status; + return this; + } + + public Builder setError(ErrorType error) { + this.error = error; + return this; + } + + public Builder setMessage(String message) { + this.message = message; + return this; + } + + public Builder setStackTrace(String stackTrace) { + this.stackTrace = stackTrace; + return this; + } + + /** + * Builds the RestError object. + * + * @return a new instance of RestError + */ + public RestError build() { + ErrorRS errorRS = new ErrorRS(); + errorRS.setMessage(message); + errorRS.setStackTrace(stackTrace); + errorRS.setErrorType(error); + + return new RestError(status, errorRS); + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestErrorDefinition.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestErrorDefinition.java new file mode 100644 index 00000000..6feda284 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestErrorDefinition.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +import com.epam.reportportal.auth.rules.commons.exception.message.ExceptionMessageBuilder; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import org.springframework.http.HttpStatus; + +/** + * REST Error template. Created to be able to configure error templates in Spring's IoC container. + * + * @author Andrei Varabyeu + */ +public class RestErrorDefinition { + + private final HttpStatus httpStatus; + private final ErrorType error; + private final ExceptionMessageBuilder exceptionMessageBuilder; + + public RestErrorDefinition(HttpStatus httpStatus, ErrorType error, + ExceptionMessageBuilder exceptionMessageBuilder) { + super(); + this.httpStatus = httpStatus; + this.error = error; + this.exceptionMessageBuilder = exceptionMessageBuilder; + } + + public RestErrorDefinition(int httpStatus, ErrorType error, + ExceptionMessageBuilder exceptionMessageBuilder) { + this(HttpStatus.valueOf(httpStatus), error, exceptionMessageBuilder); + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } + + public ErrorType getError() { + return error; + } + + public String getExceptionMessage(T e) { + return exceptionMessageBuilder.buildMessage(e); + } + + public ExceptionMessageBuilder getExceptionMessageBuilder() { + return exceptionMessageBuilder; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestExceptionHandler.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestExceptionHandler.java new file mode 100644 index 00000000..76113e87 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/RestExceptionHandler.java @@ -0,0 +1,177 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.http.server.ServletServerHttpRequest; +import org.springframework.http.server.ServletServerHttpResponse; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.multipart.support.MissingServletRequestPartException; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; +import org.springframework.web.util.WebUtils; + +/** + * Custom implementation of Spring's error handler. + * + * @author Andrei Varabyeu + */ +public class RestExceptionHandler extends DefaultHandlerExceptionResolver { + + /** + * Error Resolver + */ + private ErrorResolver errorResolver; + + /** + * Set of converters to be able to render response. + */ + private List> messageConverters; + + public void setErrorResolver(ErrorResolver errorResolver) { + this.errorResolver = errorResolver; + } + + public void setMessageConverters(List> messageConverters) { + this.messageConverters = messageConverters; + } + + + @Override + protected ModelAndView doResolveException(HttpServletRequest request, + HttpServletResponse response, Object handler, Exception ex) { + LoggerFactory.getLogger(this.getClass()).error("Handled error: ", ex); + ModelAndView defaultError = super.doResolveException(request, response, handler, ex); + if (null != defaultError) { + return defaultError; + } + + return handleCustomException(request, response, ex); + } + + protected ModelAndView handleCustomException(HttpServletRequest request, + HttpServletResponse response, Exception ex) { + ServletWebRequest webRequest = new ServletWebRequest(request, response); + + RestError error = errorResolver.resolveError(ex); + if (error == null) { + return null; + } + applyStatusIfPossible(webRequest, error.getHttpStatus()); + + try { + return handleResponseBody(error.getErrorRs(), webRequest); + } catch (IOException e) { + if (logger.isWarnEnabled()) { + logger.warn("Unable to write error message", e); + } + return null; + } + } + + private void applyStatusIfPossible(ServletWebRequest webRequest, HttpStatus status) { + if (!WebUtils.isIncludeRequest(webRequest.getRequest())) { + webRequest.getResponse().setStatus(status.value()); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private ModelAndView handleResponseBody(Object body, ServletWebRequest webRequest) + throws HttpMessageNotWritableException, IOException { + + HttpInputMessage inputMessage = new ServletServerHttpRequest(webRequest.getRequest()); + + List acceptedMediaTypes = inputMessage.getHeaders().getAccept(); + if (acceptedMediaTypes.isEmpty()) { + acceptedMediaTypes = Collections.singletonList(MediaType.ALL); + } + + MediaType.sortByQualityValue(acceptedMediaTypes); + + HttpOutputMessage outputMessage = new ServletServerHttpResponse(webRequest.getResponse()); + + Class bodyType = body.getClass(); + + List> converters = this.messageConverters; + + if (converters != null) { + for (MediaType acceptedMediaType : acceptedMediaTypes) { + for (HttpMessageConverter messageConverter : converters) { + if (messageConverter.canWrite(bodyType, acceptedMediaType)) { + messageConverter.write(body, acceptedMediaType, outputMessage); + // return empty model and view to short circuit the + // iteration and to let + // Spring know that we've rendered the view ourselves: + return new ModelAndView(); + } + } + } + } + + if (logger.isWarnEnabled()) { + logger.warn( + "Could not find HttpMessageConverter that supports return type [" + bodyType + "] and " + + acceptedMediaTypes); + } + return null; + } + + /** + * Override default behavior and handle bind exception as custom exception + */ + @Override + protected ModelAndView handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, + HttpServletRequest request, + HttpServletResponse response, Object handler) throws IOException { + return handleCustomException(request, response, ex); + } + + @Override + protected ModelAndView handleHttpMessageNotReadable(HttpMessageNotReadableException ex, + HttpServletRequest request, + HttpServletResponse response, Object handler) throws IOException { + return handleCustomException(request, response, ex); + } + + @Override + protected ModelAndView handleMissingServletRequestPartException( + MissingServletRequestPartException ex, HttpServletRequest request, + HttpServletResponse response, Object handler) throws IOException { + return handleCustomException(request, response, ex); + } + + @Override + protected ModelAndView handleMissingServletRequestParameter( + MissingServletRequestParameterException ex, HttpServletRequest request, + HttpServletResponse response, Object handler) throws IOException { + return handleCustomException(request, response, ex); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/StatusCodeMapping.java b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/StatusCodeMapping.java new file mode 100644 index 00000000..ecf44940 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/exception/rest/StatusCodeMapping.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.exception.rest; + +import com.epam.reportportal.auth.rules.exception.ErrorType; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import org.springframework.http.HttpStatus; + +/** + * {@link ErrorType} to {@link HttpStatus} mapping. + * + * @author Andrei Varabyeu + */ +public class StatusCodeMapping { + + private StatusCodeMapping() { + + } + + private static final Map MAPPING = new HashMap<>() { + private static final long serialVersionUID = 1L; + + { + put(ErrorType.ROLE_NOT_FOUND, HttpStatus.NOT_FOUND); + put(ErrorType.USER_NOT_FOUND, HttpStatus.NOT_FOUND); + put(ErrorType.AUTH_INTEGRATION_NOT_FOUND, HttpStatus.NOT_FOUND); + put(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, HttpStatus.NOT_FOUND); + + // ExternalSystem related + put(ErrorType.INTEGRATION_NOT_FOUND, HttpStatus.NOT_FOUND); + put(ErrorType.INTEGRATION_ALREADY_EXISTS, HttpStatus.CONFLICT); + put(ErrorType.INCORRECT_AUTHENTICATION_TYPE, HttpStatus.BAD_REQUEST); + put(ErrorType.UNABLE_INTERACT_WITH_INTEGRATION, HttpStatus.CONFLICT); + + /* Authentication related */ + put(ErrorType.ACCESS_DENIED, HttpStatus.FORBIDDEN); + put(ErrorType.ADDRESS_LOCKED, HttpStatus.FORBIDDEN); + + put(ErrorType.INCORRECT_REQUEST, HttpStatus.BAD_REQUEST); + put(ErrorType.BAD_REQUEST_ERROR, HttpStatus.BAD_REQUEST); + put(ErrorType.UNCLASSIFIED_ERROR, HttpStatus.INTERNAL_SERVER_ERROR); + put(ErrorType.UNCLASSIFIED_REPORT_PORTAL_ERROR, HttpStatus.INTERNAL_SERVER_ERROR); + + } + }; + + public static HttpStatus getHttpStatus(ErrorType errorType, HttpStatus defaultStatus) { + return getHttpStatus(errorType).orElse(defaultStatus); + } + + public static Optional getHttpStatus(ErrorType errorType) { + return Optional.ofNullable(MAPPING.get(errorType)); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/AlwaysFailRuleValidator.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/AlwaysFailRuleValidator.java new file mode 100644 index 00000000..4d6121db --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/AlwaysFailRuleValidator.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; + +/** + * Added for rules which is going to be always fail + * + * @author Andrei Varabyeu + */ +public class AlwaysFailRuleValidator { + + public void withError(ErrorType errorType, Object... args) { + throw new ReportPortalException(errorType, args); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/BusinessRule.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/BusinessRule.java new file mode 100644 index 00000000..eaf894f1 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/BusinessRule.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + + +import java.util.function.Predicate; +import java.util.function.Supplier; + +/** + * Domain objects verification utility, based on predicates as business rules. + * + * @author Dzianis Shlychkou + */ +public class BusinessRule { + + private BusinessRule() { + //should be created via factory-methods only + } + + /** + * Create rule from object to be verified, predicate and error message in case of violation. + * + * @param Type of object being checked + * @param object Object to be validated + * @param predicate Validation predicate + * @param messageSupplier Error message supplier + * @return Validator + */ + public static DefaultRuleValidator expect(T object, Predicate predicate, + Supplier messageSupplier) { + return new DefaultRuleValidator<>(object, predicate, messageSupplier); + } + + /** + * Create rule from object to be verified, predicate. + * + * @param Type of object being checked + * @param object Object to be validated + * @param predicate Validation predicate + * @return Validator + */ + public static ErrorTypeBasedRuleValidator expect(T object, Predicate predicate) { + return new ErrorTypeBasedRuleValidator<>(object, predicate); + } + + /** + * For cases where we are going to fail something. + * + * @return {@link AlwaysFailRuleValidator} + */ + public static AlwaysFailRuleValidator fail() { + return new AlwaysFailRuleValidator(); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/BusinessRuleViolationException.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/BusinessRuleViolationException.java new file mode 100644 index 00000000..8571bbe8 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/BusinessRuleViolationException.java @@ -0,0 +1,29 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + + +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.trimMessage; +import static com.epam.reportportal.auth.rules.exception.ReportPortalException.MAX_ERROR_MESSAGE_LENGTH; + +public class BusinessRuleViolationException extends Exception { + + public BusinessRuleViolationException(String message) { + super(trimMessage(message, MAX_ERROR_MESSAGE_LENGTH)); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/DefaultRuleValidator.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/DefaultRuleValidator.java new file mode 100644 index 00000000..b86a0865 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/DefaultRuleValidator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + + +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public class DefaultRuleValidator extends RuleValidator { + + private final Supplier message; + + public DefaultRuleValidator(T target, Predicate predicate, + Supplier message) { + super(target, predicate); + this.message = message; + } + + /** + * Verifies predicate and throws {@link BusinessRuleViolationException} is there is violation + * + * @throws BusinessRuleViolationException if rule condition is not passed + */ + public void verify() throws BusinessRuleViolationException { + if (!predicate.test(target)) { + throw new BusinessRuleViolationException(message.get()); + } + } + + /** + * Verifies predicate and throws {@link ReportPortalException} if there is violation + * + * @param t - exception to thrown instead of {@link ReportPortalException} + */ + public void verify(Class t) { + if (!predicate.test(target)) { + ReportPortalException toBeThrowed; + try { + toBeThrowed = t.getConstructor(String.class).newInstance( + message.get()); + } catch (Exception e) { + throw new ReportPortalException(message.get(), e); + } + throw toBeThrowed; + } + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/ErrorTypeBasedRuleValidator.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/ErrorTypeBasedRuleValidator.java new file mode 100644 index 00000000..066f3c89 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/ErrorTypeBasedRuleValidator.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; +import java.util.function.Predicate; + +public class ErrorTypeBasedRuleValidator extends RuleValidator { + + public ErrorTypeBasedRuleValidator(T target, Predicate predicate) { + super(target, predicate); + } + + public void verify(ErrorType errorType, Object... args) { + if (!predicate.test(target)) { + throw new ReportPortalException(errorType, args); + } + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/RuleValidator.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/RuleValidator.java new file mode 100644 index 00000000..7685aabc --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/RuleValidator.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + + +import java.util.function.Predicate; + +public abstract class RuleValidator { + + protected final Predicate predicate; + protected final T target; + + protected RuleValidator(T target, Predicate predicate) { + this.target = target; + this.predicate = predicate; + + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/commons/validation/Suppliers.java b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/Suppliers.java new file mode 100644 index 00000000..b652932b --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/commons/validation/Suppliers.java @@ -0,0 +1,132 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.commons.validation; + +import static com.google.common.base.Strings.isNullOrEmpty; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.CharMatcher; +import java.util.Arrays; +import java.util.function.Supplier; +import org.slf4j.helpers.MessageFormatter; + +/** + * Several useful suppliers. + * + * @author Andrei Varabyeu + */ +public class Suppliers { + + private static final CharMatcher REPLACEMENT_SYMBOLS = CharMatcher.anyOf("{}"); + + private Suppliers() { + + } + + /** + * Preemptive supplier for string. Do not do any actions with string + * + * @param string String to be supplied + * @return Supplied String + */ + public static Supplier stringSupplier(final String string) { + return () -> string; + } + + /** + * Formatted supplier. Applies {@link MessageFormatter} to be able to pass formatted string with + * parameters as we did int slf4j. Good approach to avoid string concatenation before we really + * need it + * + * @param string String to be supplied + * @param parameters Formatter parameters + * @return Supplied String + */ + public static Supplier formattedSupplier(final String string, + final Object... parameters) { + return new Supplier() { + @Override + public String get() { + return clearPlaceholders(MessageFormatter.arrayFormat(string, parameters).getMessage()); + } + + @Override + public String toString() { + return get(); + } + }; + } + + /** + * Formatted supplier. Applies {@link MessageFormatter} to be able to pass formatted string with + * parameters as we did int slf4j. Good approach to avoid string concatenation before we really + * need it + * + * @param string String to be supplied + * @param parameters Formatter parameters + * @return Supplied String + */ + public static Supplier formattedSupplier(final String string, + final Supplier... parameters) { + return new Supplier() { + @Override + public String get() { + return clearPlaceholders(MessageFormatter.arrayFormat(string, + Arrays.stream(parameters).map(Supplier::get).toArray()) + .getMessage()); + } + + @Override + public String toString() { + return get(); + } + }; + } + + /** + * Clears placeholders in the message + * + * @param message Message to be cleared + * @return Cleared string + */ + @VisibleForTesting + public static String clearPlaceholders(String message) { + String cleared = message; + if (formattedMessage(message)) { + cleared = REPLACEMENT_SYMBOLS.removeFrom(message).trim(); + } + return cleared; + } + + /** + * Checks whether placeholder characters are present in the string + * + * @param str String to check + * @return TRUE if at least one placeholder symbol is present + */ + public static boolean formattedMessage(String str) { + return !isNullOrEmpty(str) && REPLACEMENT_SYMBOLS.matchesAnyOf(str); + } + + public static String trimMessage(String message, int maxLength) { + if (message.length() > maxLength) { + return message.substring(0, maxLength); + } + return message; + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/exception/ErrorRS.java b/src/main/java/com/epam/reportportal/auth/rules/exception/ErrorRS.java new file mode 100644 index 00000000..ee65f80f --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/exception/ErrorRS.java @@ -0,0 +1,134 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.exception; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.io.IOException; +import java.io.Serializable; +import lombok.Getter; +import lombok.Setter; + +/** + * Base Error response body for all Report Portal exceptions + * + * @author Andrei Varabyeu + */ +@Setter +@Getter +@JsonPropertyOrder({"errorCode", "message", "stackTrace"}) +@JsonInclude(Include.NON_NULL) +public class ErrorRS implements Serializable { + + /** + * Generated SVUID + */ + private static final long serialVersionUID = -3717290684860161862L; + + @JsonSerialize(using = ErrorTypeSerializer.class) + @JsonDeserialize(using = ErrorTypeDeserializer.class) + @JsonProperty("errorCode") + private ErrorType errorType; + + @JsonProperty("stackTrace") + private String stackTrace; + + @JsonProperty("message") + private String message; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((errorType == null) ? 0 : errorType.hashCode()); + result = prime * result + ((message == null) ? 0 : message.hashCode()); + result = prime * result + ((stackTrace == null) ? 0 : stackTrace.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; + } + ErrorRS other = (ErrorRS) obj; + if (errorType != other.errorType) { + return false; + } + if (message == null) { + if (other.message != null) { + return false; + } + } else if (!message.equals(other.message)) { + return false; + } + if (stackTrace == null) { + return other.stackTrace == null; + } else { + return stackTrace.equals(other.stackTrace); + } + } + + private static class ErrorTypeDeserializer extends JsonDeserializer { + + @Override + public ErrorType deserialize(JsonParser parser, DeserializationContext context) + throws IOException { + ObjectCodec oc = parser.getCodec(); + JsonNode node = oc.readTree(parser); + return ErrorType.getByCode(node.asInt()); + + } + + } + + private static class ErrorTypeSerializer extends JsonSerializer { + + @Override + public void serialize(ErrorType error, JsonGenerator jsonGenerator, + SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeNumber(error.getCode()); + } + + } + + @Override + public String toString() { + return "ErrorRS{" + "errorType=" + errorType + + ", stackTrace='" + stackTrace + '\'' + + ", message='" + message + '\'' + + '}'; + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/exception/ErrorType.java b/src/main/java/com/epam/reportportal/auth/rules/exception/ErrorType.java new file mode 100644 index 00000000..0d9ec9f5 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/exception/ErrorType.java @@ -0,0 +1,122 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.exception; + +import lombok.Getter; + +/** + * Report Portal's exception list + * + * @author Andrei Varabyeu + */ +@Getter +public enum ErrorType { + + /** + * Incorrect Report Portal WS Request + */ + INCORRECT_REQUEST(4001, "Incorrect Request. {}"), + + /** + * Access Denied + */ + ACCESS_DENIED(4003, "You do not have enough permissions. {}"), + /** + * Access Denied + */ + ADDRESS_LOCKED(4004, "Address is locked due to several incorrect login attempts"), + + /** + * If specified by id role not found + */ + ROLE_NOT_FOUND(4045, "Project role '{}' not found. Did you use correct Role Name?"), + + /** + * If specified by login User not found + */ + USER_NOT_FOUND(4046, "User '{}' not found. {}"), + + /** + * Integration not found + */ + INTEGRATION_NOT_FOUND(40413, "Integration with ID '{}' not found. Did you use correct ID?"), + + /** + * If specified Authentication extension isn't found + */ + AUTH_INTEGRATION_NOT_FOUND(40419, "Auth integration '{}' not found. Did you use correct name?"), + + /** + * If binary data not found + */ + UNABLE_TO_LOAD_BINARY_DATA(40427, "Unable to load binary data by id '{}'"), + + /** + * Unable to recognize provided authentication type + */ + INCORRECT_AUTHENTICATION_TYPE(40015, "Incorrect authentication type: {}"), + + /** + * Impossible to interact with integration + */ + UNABLE_INTERACT_WITH_INTEGRATION(40302, "Impossible interact with integration. {}"), + + /** + * Unable create duplicate of integration + */ + INTEGRATION_ALREADY_EXISTS(40910, + "Integration '{}' already exists. You couldn't create the duplicate."), + + /** + * Base Error If Request sent with incorrect parameters + */ + BAD_REQUEST_ERROR(40016, "Error in handled Request. Please, check specified parameters: '{}'"), + + /** + * Base ReportPortal Exception. Try to avoid this type and create more custom + */ + UNCLASSIFIED_REPORT_PORTAL_ERROR(5001, "Unclassified Report Portal Error"), + + /** + * Use it If there are no any other exceptions. There should by no such exception + */ + UNCLASSIFIED_ERROR(5000, "Unclassified error"); + + private final int code; + + private final String description; + + ErrorType(int code, String description) { + this.code = code; + this.description = description; + } + + /** + * Get instance by code + * + * @param code Error Code + * @return ErrorType + */ + public static ErrorType getByCode(int code) { + for (ErrorType error : values()) { + if (error.getCode() == code) { + return error; + } + } + throw new IllegalArgumentException("Unable to find Error with code '" + code + "'"); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/rules/exception/ReportPortalException.java b/src/main/java/com/epam/reportportal/auth/rules/exception/ReportPortalException.java new file mode 100644 index 00000000..02849d57 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/rules/exception/ReportPortalException.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.rules.exception; + +import static com.epam.reportportal.auth.rules.commons.validation.Suppliers.trimMessage; + +import com.epam.reportportal.auth.rules.commons.validation.Suppliers; +import lombok.Getter; + + +/** + * Base Report Portal Exception + * + * @author Andrei Varabyeu + */ +@Getter +public class ReportPortalException extends RuntimeException { + + public static final int MAX_ERROR_MESSAGE_LENGTH = 10000; + + private static final long serialVersionUID = -7599195984281555977L; + + private ErrorType errorType; + private Object[] parameters; //NOSONAR + + public ReportPortalException(String message) { + super(message); + } + + public ReportPortalException(ErrorType errorType, Object... parameters) { + super(trimMessage(Suppliers.formattedSupplier(errorType.getDescription(), parameters).get(), + MAX_ERROR_MESSAGE_LENGTH)); + this.errorType = errorType; + this.parameters = parameters; + } + + public ReportPortalException(String message, Throwable e) { + super(trimMessage(message, MAX_ERROR_MESSAGE_LENGTH), e); + } + +} diff --git a/src/main/java/com/epam/reportportal/auth/store/MutableClientRegistrationRepository.java b/src/main/java/com/epam/reportportal/auth/store/MutableClientRegistrationRepository.java index 3e617bc0..504ceee2 100644 --- a/src/main/java/com/epam/reportportal/auth/store/MutableClientRegistrationRepository.java +++ b/src/main/java/com/epam/reportportal/auth/store/MutableClientRegistrationRepository.java @@ -18,11 +18,11 @@ import static com.epam.reportportal.auth.integration.converter.OAuthRegistrationConverters.TO_SPRING; -import com.epam.reportportal.rules.commons.validation.Suppliers; -import com.epam.reportportal.rules.exception.ReportPortalException; -import com.epam.ta.reportportal.dao.OAuthRegistrationRepository; -import com.epam.ta.reportportal.entity.oauth.OAuthRegistration; -import com.epam.reportportal.rules.exception.ErrorType; +import com.epam.reportportal.auth.dao.OAuthRegistrationRepository; +import com.epam.reportportal.auth.entity.oauth.OAuthRegistration; +import com.epam.reportportal.auth.rules.commons.validation.Suppliers; +import com.epam.reportportal.auth.rules.exception.ErrorType; +import com.epam.reportportal.auth.rules.exception.ReportPortalException; import java.util.Collection; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/epam/reportportal/auth/util/AuthUtils.java b/src/main/java/com/epam/reportportal/auth/util/AuthUtils.java index bfc3f5e9..ccda5841 100644 --- a/src/main/java/com/epam/reportportal/auth/util/AuthUtils.java +++ b/src/main/java/com/epam/reportportal/auth/util/AuthUtils.java @@ -16,9 +16,9 @@ package com.epam.reportportal.auth.util; -import static com.epam.ta.reportportal.commons.EntityUtils.normalizeId; +import static com.epam.reportportal.auth.commons.EntityUtils.normalizeId; -import com.epam.ta.reportportal.entity.user.UserRole; +import com.epam.reportportal.auth.entity.user.UserRole; import java.util.Collections; import java.util.List; import java.util.function.Function; diff --git a/src/main/java/com/epam/reportportal/auth/util/FeatureFlagHandler.java b/src/main/java/com/epam/reportportal/auth/util/FeatureFlagHandler.java new file mode 100644 index 00000000..c2cd9631 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/util/FeatureFlagHandler.java @@ -0,0 +1,38 @@ +package com.epam.reportportal.auth.util; + +import com.epam.reportportal.auth.entity.enums.FeatureFlag; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * Component for checking enabled feature flags. + * + * @author Ivan Kustau + */ +@Component +public class FeatureFlagHandler { + + private final Set enabledFeatureFlagsSet = new HashSet<>(); + + /** + * Initialises {@link FeatureFlagHandler} by environment variable with enabled feature flags. + * + * @param featureFlags Set of enabled feature flags + */ + public FeatureFlagHandler( + @Value("#{'${rp.feature.flags}'.split(',')}") Set featureFlags) { + + if (!CollectionUtils.isEmpty(featureFlags)) { + featureFlags.stream().map(FeatureFlag::fromString).filter(Optional::isPresent) + .map(Optional::get).forEach(enabledFeatureFlagsSet::add); + } + } + + public boolean isEnabled(FeatureFlag featureFlag) { + return enabledFeatureFlagsSet.contains(featureFlag); + } +} diff --git a/src/main/java/com/epam/reportportal/auth/util/PersonalProjectService.java b/src/main/java/com/epam/reportportal/auth/util/PersonalProjectService.java new file mode 100644 index 00000000..d3b63034 --- /dev/null +++ b/src/main/java/com/epam/reportportal/auth/util/PersonalProjectService.java @@ -0,0 +1,127 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.reportportal.auth.util; + +import static com.epam.reportportal.auth.entity.project.ProjectUtils.defaultIssueTypes; +import static com.epam.reportportal.auth.entity.project.ProjectUtils.defaultProjectAttributes; +import static com.google.common.base.Strings.isNullOrEmpty; + +import com.epam.reportportal.auth.dao.AttributeRepository; +import com.epam.reportportal.auth.dao.IssueTypeRepository; +import com.epam.reportportal.auth.dao.ProjectRepository; +import com.epam.reportportal.auth.entity.Metadata; +import com.epam.reportportal.auth.entity.enums.ProjectAttributeEnum; +import com.epam.reportportal.auth.entity.enums.ProjectType; +import com.epam.reportportal.auth.entity.project.Project; +import com.epam.reportportal.auth.entity.project.ProjectRole; +import com.epam.reportportal.auth.entity.user.ProjectUser; +import com.epam.reportportal.auth.entity.user.User; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Sets; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * Generates Personal project for provided user + * + * @author Andrei Varabyeu + */ +@Service +public final class PersonalProjectService { + + public static final String PERSONAL_PROJECT_POSTFIX = "_personal"; + private final ProjectRepository projectRepository; + private final AttributeRepository attributeRepository; + private final IssueTypeRepository issueTypeRepository; + + @Autowired + public PersonalProjectService(ProjectRepository projectRepository, + AttributeRepository attributeRepository, + IssueTypeRepository issueTypeRepository) { + this.projectRepository = projectRepository; + this.attributeRepository = attributeRepository; + this.issueTypeRepository = issueTypeRepository; + } + + /** + * Prefix from username with replaced dots as underscores + * + * @param username Name of user + * @return Corresponding personal project name + */ + @VisibleForTesting + private String generatePersonalProjectName(String username) { + String initialName = getProjectPrefix(username); + + String name = initialName; + //iterate until we find free project name + for (int i = 1; projectRepository.existsByName(name); i++) { + name = initialName + "_" + i; + } + + return name; + } + + /** + * Generates personal project for provided user + * + * @param user User project should be created for + * @return Built Project object + */ + public Project generatePersonalProject(User user) { + Project project = new Project(); + project.setName(generatePersonalProjectName(user.getLogin())); + project.setCreationDate(Instant.now()); + project.setProjectType(ProjectType.PERSONAL); + + ProjectUser projectUser = new ProjectUser() + .withUser(user) + .withProjectRole(ProjectRole.PROJECT_MANAGER) + .withProject(project); + project.setUsers(Sets.newHashSet(projectUser)); + + project.setMetadata(new Metadata(Collections.singletonMap("additional_info", + "Personal project of " + (isNullOrEmpty(user.getFullName()) ? user.getLogin() + : user.getFullName()) + ))); + + var attrs = Arrays.stream(ProjectAttributeEnum.values()) + .map(ProjectAttributeEnum::getAttribute) + .collect(Collectors.toSet()); + project.setProjectAttributes( + defaultProjectAttributes(project, attributeRepository.findAllByNameIn(attrs))); + project.setProjectIssueTypes( + defaultIssueTypes(project, issueTypeRepository.getDefaultIssueTypes())); + + return project; + } + + /** + * Generates prefix for personal project + * + * @param username Name of user + * @return Prefix + */ + public String getProjectPrefix(String username) { + String projectName = username.replaceAll("\\.", "_"); + return (projectName + PERSONAL_PROJECT_POSTFIX).toLowerCase(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 08dc1efc..d9aa2394 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -90,4 +90,4 @@ datastore.secretKey= datastore.bucketPrefix= prj- datastore.bucketPostfix= datastore.defaultBucketName= rp-bucket -datastore.region=us-west-1 \ No newline at end of file +datastore.region=us-west-1 diff --git a/src/test/java/com/epam/auth/reportportal/BaseTest.java b/src/test/java/com/epam/auth/reportportal/BaseTest.java new file mode 100644 index 00000000..87c41a25 --- /dev/null +++ b/src/test/java/com/epam/auth/reportportal/BaseTest.java @@ -0,0 +1,137 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.auth.reportportal; + +import com.epam.auth.reportportal.config.TestConfig; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Stream; +import lombok.SneakyThrows; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.org.apache.commons.io.FileUtils; + + +/** + * Base class for all test classes. It sets up the PostgreSQL container and applies migration + * scripts. It also configures dynamic properties for the test context. + */ +@Testcontainers +@Log4j2 +@SpringBootTest(classes = TestConfig.class, webEnvironment = WebEnvironment.DEFINED_PORT) +@ActiveProfiles({"unittest"}) +public abstract class BaseTest { + + private static final String MIGRATIONS_PATH = "migrations/migrations/"; + public static final String DB_MIGRATION_PATH = "build/resources/test/db/migration"; + + private static final String POSTGRES_CONTAINER = "postgres:16-alpine"; + private static final String LDAP_CONTAINER = "bitnami/openldap:latest"; + private static final String MINIO_CONTAINER = "minio/minio"; + + + @LocalServerPort + private Integer port; + + static PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRES_CONTAINER) + .withAccessToHost(true) + .withDatabaseName("reportportal"); + + + @SneakyThrows + private static void applyMigrationScripts() { + try (Stream stream = Files.list(Paths.get(MIGRATIONS_PATH))) { + log.info("Copy database scripts"); + stream + .filter(file -> !Files.isDirectory(file)) + .map(Path::getFileName) + .map(Path::toString) + .filter(filename -> filename.contains(".up.sql")) + .map(filename -> { + int n = 3 - filename.indexOf("_"); + return StringUtils.repeat(" ", n) + filename; + }) + .forEach(filename -> { + try { + var file = new File( + DB_MIGRATION_PATH + "/V" + filename.replace(" ", "0")); + FileUtils.writeStringToFile(file, "\n" + + FileUtils.readFileToString(new File(MIGRATIONS_PATH + filename.trim()), + StandardCharsets.UTF_8), StandardCharsets.UTF_8); + + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + // get sorted list of migration files + try (Stream copiedFiles = Files.list(Paths.get(DB_MIGRATION_PATH))) { + var list = copiedFiles + .map(Path::getFileName) + .map(Path::toString) + .sorted() + .peek(System.out::println) + .map(filename -> "db/migration/" + filename) + .toList(); + + postgres.withInitScripts(list); + + } + + } + } + + @BeforeAll + static void beforeAll() { + applyMigrationScripts(); + postgres.start(); + log.info("PostgreSQL container started on port: {}", postgres.getFirstMappedPort()); + } + + @AfterAll + static void afterAll() { + postgres.stop(); + } + + @DynamicPropertySource + static void configureProperties(DynamicPropertyRegistry registry) { + registry.add("rp.datasource.jdbcUrl", postgres::getJdbcUrl); + registry.add("rp.datasource.username", postgres::getUsername); + registry.add("rp.datasource.password", postgres::getPassword); + registry.add("rp.initial.admin.password", () -> "testpassword"); + } + +} + + + + + diff --git a/src/test/java/com/epam/auth/reportportal/config/TestConfig.java b/src/test/java/com/epam/auth/reportportal/config/TestConfig.java new file mode 100644 index 00000000..896ccf7f --- /dev/null +++ b/src/test/java/com/epam/auth/reportportal/config/TestConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 EPAM Systems + * + * 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 com.epam.auth.reportportal.config; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Profile; +import org.springframework.security.oauth2.provider.token.AccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; + +/** + * Configuration class for unit tests. + */ +@SpringBootConfiguration +@EnableConfigurationProperties +@EnableAutoConfiguration(exclude = {QuartzAutoConfiguration.class}) +@ComponentScan(basePackages = {"com.epam.reportportal"}) +public class TestConfig { + + @Bean + @Profile("unittest") + public JwtAccessTokenConverter accessTokenConverter(AccessTokenConverter accessTokenConverter) { + JwtAccessTokenConverter jwtConverter = new JwtAccessTokenConverter(); + jwtConverter.setSigningKey("123"); + jwtConverter.setAccessTokenConverter(accessTokenConverter); + return jwtConverter; + } + + +} diff --git a/src/test/java/com/epam/auth/reportportal/dao/UserRepositoryCustomImplTest.java b/src/test/java/com/epam/auth/reportportal/dao/UserRepositoryCustomImplTest.java new file mode 100644 index 00000000..9525f2d0 --- /dev/null +++ b/src/test/java/com/epam/auth/reportportal/dao/UserRepositoryCustomImplTest.java @@ -0,0 +1,27 @@ +package com.epam.auth.reportportal.dao; + +import com.epam.auth.reportportal.BaseTest; +import com.epam.reportportal.auth.dao.UserRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class UserRepositoryCustomImplTest extends BaseTest { + + @Autowired + UserRepository userRepository; + + @Test + void findUserDetails() { + var user = userRepository.findByLogin("superadmin") + .orElseThrow(); + Assertions.assertEquals("superadmin", user.getLogin()); + } + + @Test + void findUserDetailsNotFound() { + var user = userRepository.findByLogin("notfound"); + Assertions.assertTrue(user.isEmpty()); + } + +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 00000000..a20a31a4 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,93 @@ +info.build.name=Authorization Service +info.build.description=Unified Authorization Trap for all ReportPortal's Services +info.build.version=test-version.1 +info.build.repo=${repo} +info.build.branch=${branch} +management.endpoints.web.base-path=/ +management.endpoints.web.exposure.include=info, health +rp.feature.flags= +datastore.thumbnail.attachment.width=\${rp.binarystore.thumbnail.attachment.width:80} +datastore.thumbnail.attachment.height=\${rp.binarystore.thumbnail.attachment.height:60} +datastore.thumbnail.avatar.width=\${rp.binarystore.thumbnail.avatar.width:40} +datastore.thumbnail.avatar.height=\${rp.binarystore.thumbnail.avatar.height:60} + +# Application.yaml configuration +# Server configuration +server.port=9999 +server.forward-headers-strategy=NATIVE +server.servlet.context-path=/ + +# Spring configuration +spring.application.name=uat +spring.jackson.default-property-inclusion=non_null +spring.session.store-type=jdbc +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +spring.jpa.generate-ddl=false +spring.jpa.hibernate.ddl-auto=none +spring.profiles.active=\${rp.profiles:default} +spring.web.locale=en_US +spring.web.locale-resolver=fixed + +springdoc.default-produces-media-type=application/json +springdoc.api-docs.path=/api-docs +springdoc.api-docs.writer-with-order-by-keys=true + +# Logging configuration +logging.level.org.springframework.security=info +logging.level.org.hibernate=info +logging.level.org.hibernate.stat=info +logging.level.org.springframework.web.bind=fatal + +# Custom reportportal configuration +rp.datasource.type=com.zaxxer.hikari.HikariDataSource +rp.datasource.driverClassName=org.postgresql.Driver +rp.datasource.jdbcUrl=\${rp.db.url} +rp.datasource.username=\${rp.db.user} +rp.datasource.password=\${rp.db.pass} +rp.datasource.maximumPoolSize=27 + +rp.db.url=jdbc:postgresql://\${rp.db.host}:\${rp.db.port}/\${rp.db.name} +rp.db.name=reportportal +rp.db.host=postgres +rp.db.port=5432 +rp.db.user= +rp.db.pass= + +rp.jwt.signing-key= +rp.jwt.token.validity-period=\${rp.session.live} + +rp.session.live=86400 + +rp.saml.session-live=4320 + +rp.auth.saml.base-path= +rp.auth.saml.entity-id=report.portal.sp.id +rp.auth.saml.key-password=password +rp.auth.saml.key-alias=report-portal-sp +rp.auth.saml.session-live=\${rp.saml.session-live} +rp.auth.saml.key-store=saml/keystore.jks +rp.auth.saml.key-store-password=password +rp.auth.saml.network-connection-timeout=5000 +rp.auth.saml.network-read-timeout=10000 +rp.auth.saml.signed-requests=false +rp.auth.saml.active-key-name=sp-signing-key +rp.auth.saml.prefix=saml/sp + +rp.amqp.addresses=amqp://\${rp.amqp.user}:\${rp.amqp.pass}@\${rp.amqp.host}:\${rp.amqp.port} +rp.amqp.base-vhost=/ +rp.amqp.host=rabbitmq +rp.amqp.port=5672 +rp.amqp.user=rabbitmq +rp.amqp.pass=rabbitmq + +# ReportPortal file storage configuration +datastore.path=data/storage +datastore.type=filesystem +datastore.endpoint= http://play.min.io +datastore.accessKey= +datastore.secretKey= +datastore.bucketPrefix= prj- +datastore.bucketPostfix= +datastore.defaultBucketName= rp-bucket +datastore.region=us-west-1