From 8fd659ad6a0e348c0e0f7f0283113f0590b33f34 Mon Sep 17 00:00:00 2001 From: Chris Malloy Date: Wed, 14 Dec 2022 07:00:27 -0400 Subject: [PATCH] Upgrading to spring boot 3.1 --- docker/entrypoint.sh | 2 +- pom.xml | 36 +- src/main/java/jasper/component/Backup.java | 2 +- .../java/jasper/component/ConfigCache.java | 2 +- src/main/java/jasper/component/Ingest.java | 15 +- src/main/java/jasper/component/IngestExt.java | 9 +- .../java/jasper/component/IngestPlugin.java | 8 +- .../java/jasper/component/IngestTemplate.java | 8 +- .../java/jasper/component/IngestUser.java | 18 +- src/main/java/jasper/component/Preload.java | 2 +- src/main/java/jasper/component/Scraper.java | 2 +- .../java/jasper/component/channel/Push.java | 2 +- .../jasper/component/cron/CronScript.java | 3 +- .../jasper/component/cron/FeedScraper.java | 2 +- src/main/java/jasper/component/cron/Pull.java | 3 +- .../java/jasper/component/cron/Scheduler.java | 3 +- .../component/delta/AsyncCacheScraper.java | 3 +- .../component/delta/AsyncWebScraper.java | 6 +- .../jasper/component/delta/DeltaScript.java | 3 +- .../java/jasper/component/delta/Mail.java | 2 +- .../jasper/config/AsyncConfiguration.java | 3 +- src/main/java/jasper/config/AuthConfig.java | 21 +- .../jasper/config/DatabaseConfiguration.java | 2 +- .../jasper/config/JacksonConfiguration.java | 15 +- .../jasper/config/LocaleConfiguration.java | 10 - .../jasper/config/ObjectMapperConfig.java | 3 +- .../java/jasper/config/PostgreSQLDialect.java | 23 +- src/main/java/jasper/config/Props.java | 18 +- src/main/java/jasper/config/RedisConfig.java | 41 +- .../jasper/config/SecurityConfiguration.java | 73 ++-- .../java/jasper/config/SingleNodeConfig.java | 73 ++-- .../java/jasper/config/WebConfigurer.java | 4 +- .../java/jasper/config/WebSocketConfig.java | 2 +- .../jasper/domain/AbstractAuditingEntity.java | 6 +- src/main/java/jasper/domain/Ext.java | 23 +- src/main/java/jasper/domain/Plugin.java | 27 +- src/main/java/jasper/domain/Ref.java | 39 +- src/main/java/jasper/domain/Template.java | 25 +- src/main/java/jasper/domain/User.java | 33 +- .../jasper/domain/validator/SchemaValid.java | 5 +- .../domain/validator/SchemaValidator.java | 5 +- .../java/jasper/repository/RefRepository.java | 7 +- .../java/jasper/repository/StreamMixin.java | 15 +- .../jasper/repository/TemplateRepository.java | 2 +- .../jasper/repository/UserRepository.java | 9 +- .../java/jasper/repository/spec/RefSpec.java | 40 +- .../java/jasper/repository/spec/TagSpec.java | 2 +- src/main/java/jasper/security/Auth.java | 2 +- .../java/jasper/security/jwt/JWTFilter.java | 10 +- src/main/java/jasper/service/ExtService.java | 2 +- .../java/jasper/service/dto/ProfileDto.java | 2 +- src/main/java/jasper/util/Crypto.java | 4 +- .../jasper/web/rest/BackupController.java | 2 +- .../java/jasper/web/rest/ExtController.java | 4 +- .../java/jasper/web/rest/GraphController.java | 4 +- .../jasper/web/rest/OriginController.java | 2 +- .../jasper/web/rest/PluginController.java | 4 +- .../jasper/web/rest/ProfileController.java | 5 +- .../java/jasper/web/rest/ProxyController.java | 2 +- .../java/jasper/web/rest/RefController.java | 6 +- .../jasper/web/rest/ReplicateController.java | 6 +- .../jasper/web/rest/ScrapeController.java | 2 +- .../jasper/web/rest/TaggingController.java | 2 +- .../jasper/web/rest/TemplateController.java | 4 +- .../java/jasper/web/rest/UserController.java | 4 +- .../jasper/web/rest/WebhookController.java | 3 +- .../web/rest/errors/ExceptionTranslator.java | 397 ++++++++++-------- .../rest/errors/ProblemDetailWithCause.java | 118 ++++++ .../resources/config/application-dblog.yml | 2 +- src/main/resources/config/application.yml | 16 +- .../StaticResourcesWebConfigurerTest.java | 48 +-- .../java/jasper/config/WebConfigurerTest.java | 43 +- .../repository/timezone/DateTimeWrapper.java | 2 +- .../java/jasper/service/UserServiceIT.java | 2 +- src/test/java/jasper/web/rest/TestUtil.java | 28 +- .../rest/errors/ExceptionTranslatorIT.java | 2 +- .../ExceptionTranslatorTestController.java | 5 +- src/test/resources/config/application.yml | 1 - 78 files changed, 739 insertions(+), 652 deletions(-) create mode 100644 src/main/java/jasper/web/rest/errors/ProblemDetailWithCause.java diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 7185411f..ac5e44a1 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -3,4 +3,4 @@ java \ "-Xmx${JASPER_HEAP:-512m}" \ "-Xms${JASPER_HEAP:-512m}" \ -XX:+UseStringDeduplication \ - org.springframework.boot.loader.JarLauncher + org.springframework.boot.loader.launch.JarLauncher diff --git a/pom.xml b/pom.xml index 042e3be3..cf142178 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.18 + 3.1.12 jasper @@ -28,18 +28,19 @@ 1.20.1 1.6.2 0.2.6 - 2.21.1 0.2.2 1.13 0.12.5 - 2021.0.9 - 0.27.0 + 2022.0.5 + 0.29.1 1.8.0 5.4.0 + 4.4 1.2 2.1.0 - 4.5.14 + 5.2.1 2.17.0 + 0.10.4 1.18.1 2.3.8 6.4.1 @@ -85,8 +86,8 @@ liquibase-core - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api com.fasterxml.jackson.module @@ -94,7 +95,7 @@ com.fasterxml.jackson.datatype - jackson-datatype-hibernate5 + jackson-datatype-hibernate5-jakarta com.fasterxml.jackson.datatype @@ -129,12 +130,18 @@ org.apache.commons commons-collections4 + ${commons.collections4.version} commons-io commons-io ${commons-io.version} + + io.vavr + vavr + ${varv.version} + org.openapitools jackson-databind-nullable @@ -151,23 +158,18 @@ ${json-patch.version} - org.hibernate + org.hibernate.orm hibernate-jpamodelgen provided - org.hibernate + org.hibernate.orm hibernate-core org.hibernate.validator hibernate-validator - - com.vladmihalcea - hibernate-types-55 - ${hibernate-types-55.version} - org.mapstruct mapstruct @@ -260,8 +262,8 @@ ${rome.version} - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 ${apache-httpclient.version} diff --git a/src/main/java/jasper/component/Backup.java b/src/main/java/jasper/component/Backup.java index d05ea890..e53a0c53 100644 --- a/src/main/java/jasper/component/Backup.java +++ b/src/main/java/jasper/component/Backup.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.micrometer.core.annotation.Counted; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityManager; import jasper.config.Props; import jasper.domain.Ext; import jasper.domain.Plugin; @@ -30,7 +31,6 @@ import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.StreamUtils; -import javax.persistence.EntityManager; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; diff --git a/src/main/java/jasper/component/ConfigCache.java b/src/main/java/jasper/component/ConfigCache.java index 8a8fdb99..27d6f23a 100644 --- a/src/main/java/jasper/component/ConfigCache.java +++ b/src/main/java/jasper/component/ConfigCache.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.annotation.PostConstruct; import jasper.component.dto.ComponentDtoMapper; import jasper.config.Config.SecurityConfig; import jasper.config.Config.ServerConfig; @@ -23,7 +24,6 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import javax.annotation.PostConstruct; import java.util.List; import java.util.Optional; import java.util.Set; diff --git a/src/main/java/jasper/component/Ingest.java b/src/main/java/jasper/component/Ingest.java index 388d867b..d943b303 100644 --- a/src/main/java/jasper/component/Ingest.java +++ b/src/main/java/jasper/component/Ingest.java @@ -1,8 +1,10 @@ package jasper.component; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityExistsException; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceException; import jasper.config.Props; import jasper.domain.Ref; import jasper.errors.AlreadyExistsException; @@ -20,9 +22,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityExistsException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; import java.time.Clock; import java.time.Instant; @@ -125,7 +124,7 @@ void ensureCreateUniqueModified(Ref ref) { break; } catch (DataIntegrityViolationException | PersistenceException e) { if (e instanceof EntityExistsException) throw new AlreadyExistsException(); - if (e.getCause() instanceof ConstraintViolationException c) { + if (e instanceof ConstraintViolationException c) { if ("ref_pkey".equals(c.getConstraintName())) throw new AlreadyExistsException(); if ("ref_modified_origin_key".equals(c.getConstraintName())) { if (count > props.getIngestMaxRetry()) throw new DuplicateModifiedDateException(); @@ -152,9 +151,9 @@ void ensureUpdateUniqueModified(Ref ref) { ref.getOrigin(), ref.getTitle(), ref.getComment(), - ref.getTags() == null ? null : objectMapper.convertValue(ref.getTags(), ArrayNode.class), - ref.getSources() == null ? null : objectMapper.convertValue(ref.getSources(), ArrayNode.class), - ref.getAlternateUrls() == null ? null : objectMapper.convertValue(ref.getAlternateUrls(), ArrayNode.class), + ref.getTags(), + ref.getSources(), + ref.getAlternateUrls(), ref.getPlugins(), ref.getMetadata(), ref.getPublished(), diff --git a/src/main/java/jasper/component/IngestExt.java b/src/main/java/jasper/component/IngestExt.java index 991aefed..56d02c5b 100644 --- a/src/main/java/jasper/component/IngestExt.java +++ b/src/main/java/jasper/component/IngestExt.java @@ -1,6 +1,9 @@ package jasper.component; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityExistsException; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceException; import jasper.config.Props; import jasper.domain.Ext; import jasper.errors.AlreadyExistsException; @@ -17,16 +20,12 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityExistsException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; import java.time.Clock; import java.time.Instant; import static jasper.component.Replicator.deletedTag; import static jasper.component.Replicator.deletorTag; import static jasper.component.Replicator.isDeletorTag; -import static org.apache.commons.lang3.StringUtils.isNotBlank; @Component public class IngestExt { @@ -109,7 +108,7 @@ void ensureCreateUniqueModified(Ext ext) { break; } catch (DataIntegrityViolationException | PersistenceException e) { if (e instanceof EntityExistsException) throw new AlreadyExistsException(); - if (e.getCause() instanceof ConstraintViolationException c) { + if (e instanceof ConstraintViolationException c) { if ("ext_pkey".equals(c.getConstraintName())) throw new AlreadyExistsException(); if ("ext_modified_origin_key".equals(c.getConstraintName())) { if (count > props.getIngestMaxRetry()) throw new DuplicateModifiedDateException(); diff --git a/src/main/java/jasper/component/IngestPlugin.java b/src/main/java/jasper/component/IngestPlugin.java index 20f0d2ed..bffcd28e 100644 --- a/src/main/java/jasper/component/IngestPlugin.java +++ b/src/main/java/jasper/component/IngestPlugin.java @@ -1,6 +1,9 @@ package jasper.component; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityExistsException; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceException; import jasper.config.Props; import jasper.domain.Plugin; import jasper.errors.AlreadyExistsException; @@ -17,9 +20,6 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityExistsException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; import java.time.Clock; import java.time.Instant; @@ -107,7 +107,7 @@ void ensureCreateUniqueModified(Plugin plugin) { break; } catch (DataIntegrityViolationException | PersistenceException e) { if (e instanceof EntityExistsException) throw new AlreadyExistsException(); - if (e.getCause() instanceof ConstraintViolationException c) { + if (e instanceof ConstraintViolationException c) { if ("plugin_pkey".equals(c.getConstraintName())) throw new AlreadyExistsException(); if ("plugin_modified_origin_key".equals(c.getConstraintName())) { if (count > props.getIngestMaxRetry()) throw new DuplicateModifiedDateException(); diff --git a/src/main/java/jasper/component/IngestTemplate.java b/src/main/java/jasper/component/IngestTemplate.java index 2cf7e1c2..3840e9f8 100644 --- a/src/main/java/jasper/component/IngestTemplate.java +++ b/src/main/java/jasper/component/IngestTemplate.java @@ -1,6 +1,9 @@ package jasper.component; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityExistsException; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceException; import jasper.config.Props; import jasper.domain.Template; import jasper.errors.AlreadyExistsException; @@ -17,9 +20,6 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityExistsException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; import java.time.Clock; import java.time.Instant; @@ -107,7 +107,7 @@ void ensureCreateUniqueModified(Template template) { break; } catch (DataIntegrityViolationException | PersistenceException e) { if (e instanceof EntityExistsException) throw new AlreadyExistsException(); - if (e.getCause() instanceof ConstraintViolationException c) { + if (e instanceof ConstraintViolationException c) { if ("template_pkey".equals(c.getConstraintName())) throw new AlreadyExistsException(); if ("template_modified_origin_key".equals(c.getConstraintName())) { if (count > props.getIngestMaxRetry()) throw new DuplicateModifiedDateException(); diff --git a/src/main/java/jasper/component/IngestUser.java b/src/main/java/jasper/component/IngestUser.java index 40d110e8..163f3aa4 100644 --- a/src/main/java/jasper/component/IngestUser.java +++ b/src/main/java/jasper/component/IngestUser.java @@ -1,8 +1,10 @@ package jasper.component; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityExistsException; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceException; import jasper.config.Props; import jasper.domain.User; import jasper.errors.AlreadyExistsException; @@ -19,9 +21,6 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityExistsException; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; import java.time.Clock; import java.time.Instant; @@ -29,6 +28,7 @@ import static jasper.component.Replicator.deletorTag; import static jasper.component.Replicator.isDeletorTag; + @Component public class IngestUser { private static final Logger logger = LoggerFactory.getLogger(IngestUser.class); @@ -106,7 +106,7 @@ void ensureCreateUniqueModified(User user) { break; } catch (DataIntegrityViolationException | PersistenceException e) { if (e instanceof EntityExistsException) throw new AlreadyExistsException(); - if (e.getCause() instanceof ConstraintViolationException c) { + if (e instanceof ConstraintViolationException c) { if ("users_pkey".equals(c.getConstraintName())) throw new AlreadyExistsException(); if ("users_modified_origin_key".equals(c.getConstraintName())) { if (count > props.getIngestMaxRetry()) throw new DuplicateModifiedDateException(); @@ -133,10 +133,10 @@ void ensureUpdateUniqueModified(User user) { user.getOrigin(), user.getName(), user.getRole(), - user.getReadAccess() == null ? null : objectMapper.convertValue(user.getReadAccess(), ArrayNode.class), - user.getWriteAccess() == null ? null : objectMapper.convertValue(user.getWriteAccess(), ArrayNode.class), - user.getTagReadAccess() == null ? null : objectMapper.convertValue(user.getTagReadAccess(), ArrayNode.class), - user.getTagWriteAccess() == null ? null : objectMapper.convertValue(user.getTagWriteAccess(), ArrayNode.class), + user.getReadAccess(), + user.getWriteAccess(), + user.getTagReadAccess(), + user.getTagWriteAccess(), user.getModified(), user.getKey(), user.getPubKey(), diff --git a/src/main/java/jasper/component/Preload.java b/src/main/java/jasper/component/Preload.java index 1d0b7c4a..08dfb194 100644 --- a/src/main/java/jasper/component/Preload.java +++ b/src/main/java/jasper/component/Preload.java @@ -1,6 +1,7 @@ package jasper.component; import io.micrometer.core.annotation.Counted; +import jakarta.annotation.PostConstruct; import jasper.config.Props; import jasper.domain.*; import jasper.repository.*; @@ -10,7 +11,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; import java.time.Duration; import java.time.Instant; import java.util.Optional; diff --git a/src/main/java/jasper/component/Scraper.java b/src/main/java/jasper/component/Scraper.java index 6455f1b5..4a7e3e47 100644 --- a/src/main/java/jasper/component/Scraper.java +++ b/src/main/java/jasper/component/Scraper.java @@ -6,6 +6,7 @@ import com.mdimension.jchronic.Options; import com.mdimension.jchronic.tags.Pointer; import io.micrometer.core.annotation.Timed; +import jakarta.persistence.EntityManager; import jasper.component.dto.JsonLd; import jasper.domain.Ref; import jasper.plugin.Scrape; @@ -19,7 +20,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; import java.io.IOException; import java.net.URISyntaxException; import java.time.Instant; diff --git a/src/main/java/jasper/component/channel/Push.java b/src/main/java/jasper/component/channel/Push.java index b6177cd8..46454dd7 100644 --- a/src/main/java/jasper/component/channel/Push.java +++ b/src/main/java/jasper/component/channel/Push.java @@ -2,6 +2,7 @@ import io.vavr.Tuple; import io.vavr.Tuple2; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.Replicator; import jasper.config.Props; @@ -15,7 +16,6 @@ import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; import java.time.Instant; import java.util.HashMap; import java.util.HashSet; diff --git a/src/main/java/jasper/component/cron/CronScript.java b/src/main/java/jasper/component/cron/CronScript.java index d910842b..3a8e299b 100644 --- a/src/main/java/jasper/component/cron/CronScript.java +++ b/src/main/java/jasper/component/cron/CronScript.java @@ -1,5 +1,6 @@ package jasper.component.cron; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.ScriptRunner; import jasper.component.Tagger; @@ -12,8 +13,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - import static jasper.domain.proj.Tag.matchesTag; import static jasper.domain.proj.Tag.publicTag; diff --git a/src/main/java/jasper/component/cron/FeedScraper.java b/src/main/java/jasper/component/cron/FeedScraper.java index 0bec20eb..4461c0f0 100644 --- a/src/main/java/jasper/component/cron/FeedScraper.java +++ b/src/main/java/jasper/component/cron/FeedScraper.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.rometools.rome.io.FeedException; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.RssParser; import jasper.component.Tagger; @@ -12,7 +13,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; import java.io.IOException; @Profile("scripts") diff --git a/src/main/java/jasper/component/cron/Pull.java b/src/main/java/jasper/component/cron/Pull.java index 277c52ac..4e2377ac 100644 --- a/src/main/java/jasper/component/cron/Pull.java +++ b/src/main/java/jasper/component/cron/Pull.java @@ -1,5 +1,6 @@ package jasper.component.cron; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.Replicator; import jasper.domain.Ref; @@ -8,8 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - @Component public class Pull implements Scheduler.CronRunner { private static final Logger logger = LoggerFactory.getLogger(Pull.class); diff --git a/src/main/java/jasper/component/cron/Scheduler.java b/src/main/java/jasper/component/cron/Scheduler.java index f5edfca6..3cb575a0 100644 --- a/src/main/java/jasper/component/cron/Scheduler.java +++ b/src/main/java/jasper/component/cron/Scheduler.java @@ -1,5 +1,6 @@ package jasper.component.cron; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.Tagger; import jasper.component.channel.Watch; @@ -13,7 +14,6 @@ import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; import java.time.Instant; import java.util.HashMap; import java.util.Map; @@ -21,7 +21,6 @@ import static jasper.domain.proj.HasTags.hasMatchingTag; import static jasper.plugin.Cron.getCron; -import static jasper.repository.spec.QualifiedTag.selector; import static jasper.repository.spec.QualifiedTag.tagOriginSelector; import static org.apache.commons.collections4.CollectionUtils.isEmpty; diff --git a/src/main/java/jasper/component/delta/AsyncCacheScraper.java b/src/main/java/jasper/component/delta/AsyncCacheScraper.java index 72bbad75..f7f3e1bc 100644 --- a/src/main/java/jasper/component/delta/AsyncCacheScraper.java +++ b/src/main/java/jasper/component/delta/AsyncCacheScraper.java @@ -1,5 +1,6 @@ package jasper.component.delta; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.FileCache; import jasper.component.Tagger; @@ -10,8 +11,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - @Profile("proxy & file-cache") @Component public class AsyncCacheScraper implements Async.AsyncRunner { diff --git a/src/main/java/jasper/component/delta/AsyncWebScraper.java b/src/main/java/jasper/component/delta/AsyncWebScraper.java index af06bee1..1a338be2 100644 --- a/src/main/java/jasper/component/delta/AsyncWebScraper.java +++ b/src/main/java/jasper/component/delta/AsyncWebScraper.java @@ -1,5 +1,7 @@ package jasper.component.delta; +import jakarta.annotation.PostConstruct; +import jakarta.persistence.EntityManager; import jasper.component.ConfigCache; import jasper.component.Ingest; import jasper.component.Scraper; @@ -13,12 +15,8 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import javax.persistence.EntityManager; - import static jasper.domain.proj.HasOrigin.origin; import static jasper.domain.proj.Tag.matchesTag; - @Profile("proxy") @Component public class AsyncWebScraper implements Async.AsyncRunner { diff --git a/src/main/java/jasper/component/delta/DeltaScript.java b/src/main/java/jasper/component/delta/DeltaScript.java index 2a2b42a6..d507297f 100644 --- a/src/main/java/jasper/component/delta/DeltaScript.java +++ b/src/main/java/jasper/component/delta/DeltaScript.java @@ -1,5 +1,6 @@ package jasper.component.delta; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.component.ScriptRunner; import jasper.component.Tagger; @@ -12,8 +13,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - import static jasper.domain.proj.Tag.matchesTag; import static org.apache.commons.lang3.StringUtils.isNotBlank; diff --git a/src/main/java/jasper/component/delta/Mail.java b/src/main/java/jasper/component/delta/Mail.java index b2f0f650..98bd4a20 100644 --- a/src/main/java/jasper/component/delta/Mail.java +++ b/src/main/java/jasper/component/delta/Mail.java @@ -1,6 +1,7 @@ package jasper.component.delta; import io.vavr.Tuple; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.domain.Ref; import jasper.domain.proj.RefUrl; @@ -16,7 +17,6 @@ import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; diff --git a/src/main/java/jasper/config/AsyncConfiguration.java b/src/main/java/jasper/config/AsyncConfiguration.java index 2fa9731e..e0ef6eea 100644 --- a/src/main/java/jasper/config/AsyncConfiguration.java +++ b/src/main/java/jasper/config/AsyncConfiguration.java @@ -11,7 +11,6 @@ import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import tech.jhipster.async.ExceptionHandlingAsyncTaskExecutor; import java.util.concurrent.Executor; @@ -36,7 +35,7 @@ public Executor getAsyncExecutor() { executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize()); executor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity()); executor.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix()); - return new ExceptionHandlingAsyncTaskExecutor(executor); + return executor; } @Override diff --git a/src/main/java/jasper/config/AuthConfig.java b/src/main/java/jasper/config/AuthConfig.java index 3a558783..73181a1e 100644 --- a/src/main/java/jasper/config/AuthConfig.java +++ b/src/main/java/jasper/config/AuthConfig.java @@ -8,10 +8,10 @@ import jasper.security.jwt.TokenProviderImpl; import jasper.security.jwt.TokenProviderImplDefault; import jasper.security.jwt.TokenProviderImplNop; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -24,7 +24,6 @@ import org.springframework.web.context.annotation.ApplicationScope; import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -47,14 +46,16 @@ RestTemplate restTemplate() { @Bean @Profile("no-ssl") - RestTemplate restTemplateBypassSSL() - throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { + RestTemplate restTemplateBypassSSL() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; HostnameVerifier hostnameVerifier = (s, sslSession) -> true; - SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); - SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier); - CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build(); - HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); + var sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); + var csf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier); + var cm = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(csf) + .build(); + var httpClient = HttpClients.custom().setConnectionManager(cm).build(); + var requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); return new RestTemplate(requestFactory); } diff --git a/src/main/java/jasper/config/DatabaseConfiguration.java b/src/main/java/jasper/config/DatabaseConfiguration.java index 5475932c..9317ac11 100644 --- a/src/main/java/jasper/config/DatabaseConfiguration.java +++ b/src/main/java/jasper/config/DatabaseConfiguration.java @@ -9,4 +9,4 @@ @EnableJpaRepositories({ "jasper.repository" }) @EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware") @EnableTransactionManagement -public class DatabaseConfiguration {} +public class DatabaseConfiguration { } diff --git a/src/main/java/jasper/config/JacksonConfiguration.java b/src/main/java/jasper/config/JacksonConfiguration.java index 53a7bad2..f74ae575 100644 --- a/src/main/java/jasper/config/JacksonConfiguration.java +++ b/src/main/java/jasper/config/JacksonConfiguration.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.json.JsonReadFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; +import com.fasterxml.jackson.datatype.hibernate5.jakarta.Hibernate5JakartaModule; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.jsontypedef.jtd.Validator; @@ -13,7 +13,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.zalando.problem.jackson.ProblemModule; import org.zalando.problem.violations.ConstraintViolationProblemModule; @Configuration @@ -74,16 +73,8 @@ public Jdk8Module jdk8TimeModule() { * Support for Hibernate types in Jackson. */ @Bean - public Hibernate5Module hibernate5Module() { - return new Hibernate5Module(); - } - - /* - * Module for serialization/deserialization of RFC7807 Problem. - */ - @Bean - public ProblemModule problemModule() { - return new ProblemModule(); + public Hibernate5JakartaModule hibernate5JakartaModule() { + return new Hibernate5JakartaModule(); } /* diff --git a/src/main/java/jasper/config/LocaleConfiguration.java b/src/main/java/jasper/config/LocaleConfiguration.java index f1452bb7..c6e4b086 100644 --- a/src/main/java/jasper/config/LocaleConfiguration.java +++ b/src/main/java/jasper/config/LocaleConfiguration.java @@ -1,23 +1,13 @@ package jasper.config; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; -import tech.jhipster.config.locale.AngularCookieLocaleResolver; @Configuration public class LocaleConfiguration implements WebMvcConfigurer { - @Bean - public LocaleResolver localeResolver() { - AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver(); - cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY"); - return cookieLocaleResolver; - } - @Override public void addInterceptors(InterceptorRegistry registry) { LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); diff --git a/src/main/java/jasper/config/ObjectMapperConfig.java b/src/main/java/jasper/config/ObjectMapperConfig.java index 681ebc30..1eb3f317 100644 --- a/src/main/java/jasper/config/ObjectMapperConfig.java +++ b/src/main/java/jasper/config/ObjectMapperConfig.java @@ -1,11 +1,10 @@ package jasper.config; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import javax.annotation.PostConstruct; - @Configuration public class ObjectMapperConfig { diff --git a/src/main/java/jasper/config/PostgreSQLDialect.java b/src/main/java/jasper/config/PostgreSQLDialect.java index 7dc7e595..f5e2f678 100644 --- a/src/main/java/jasper/config/PostgreSQLDialect.java +++ b/src/main/java/jasper/config/PostgreSQLDialect.java @@ -1,17 +1,20 @@ package jasper.config; -import org.hibernate.dialect.function.SQLFunctionTemplate; +import org.hibernate.boot.model.FunctionContributions; import org.hibernate.dialect.function.StandardSQLFunction; -import org.hibernate.type.DurationType; import org.hibernate.type.StandardBasicTypes; -import tech.jhipster.domain.util.FixedPostgreSQL95Dialect; -public class PostgreSQLDialect extends FixedPostgreSQL95Dialect { - public PostgreSQLDialect() { - super(); - registerFunction("age", new StandardSQLFunction("age", DurationType.INSTANCE)); - registerFunction("jsonb_exists", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "jsonb_exists(?1, ?2)")); - registerFunction("jsonb_set", new SQLFunctionTemplate(StandardBasicTypes.STRING, "jsonb_set(?1, ?2, ?3, ?4)")); - registerFunction("cast_to_jsonb", new SQLFunctionTemplate(StandardBasicTypes.STRING, "?1::jsonb")); +public class PostgreSQLDialect extends org.hibernate.dialect.PostgreSQLDialect { + @Override + public void initializeFunctionRegistry(FunctionContributions functionContributions) { + super.initializeFunctionRegistry(functionContributions); + var functionRegistry = functionContributions.getFunctionRegistry(); + var bool = functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.BOOLEAN); + var str = functionContributions.getTypeConfiguration().getBasicTypeRegistry().resolve(StandardBasicTypes.STRING); + functionRegistry.register("age", new StandardSQLFunction("age", StandardBasicTypes.DURATION)); + functionRegistry.registerPattern("jsonb_exists", "jsonb_exists(?1, ?2)", bool); + functionRegistry.registerPattern("jsonb_set", "jsonb_set(?1, ?2, ?3, ?4)", str); + functionRegistry.registerPattern("cast_to_jsonb", "?1::jsonb", str); } + } diff --git a/src/main/java/jasper/config/Props.java b/src/main/java/jasper/config/Props.java index 033cf00d..7ce993eb 100644 --- a/src/main/java/jasper/config/Props.java +++ b/src/main/java/jasper/config/Props.java @@ -190,16 +190,16 @@ public static class Security { @Getter @Setter public static class ApiDocs { - private String title = JHipsterDefaults.ApiDocs.title; - private String description = JHipsterDefaults.ApiDocs.description; - private String version = JHipsterDefaults.ApiDocs.version; - private String termsOfServiceUrl = JHipsterDefaults.ApiDocs.termsOfServiceUrl; - private String contactName = JHipsterDefaults.ApiDocs.contactName; - private String contactUrl = JHipsterDefaults.ApiDocs.contactUrl; - private String contactEmail = JHipsterDefaults.ApiDocs.contactEmail; + private String title = ""; + private String description = ""; + private String version = ""; + private String termsOfServiceUrl = ""; + private String contactName = ""; + private String contactUrl = ""; + private String contactEmail = ""; private License license; - private String defaultIncludePattern = JHipsterDefaults.ApiDocs.defaultIncludePattern; - private String managementIncludePattern = JHipsterDefaults.ApiDocs.managementIncludePattern; + private String defaultIncludePattern = ""; + private String managementIncludePattern = ""; private List servers; } diff --git a/src/main/java/jasper/config/RedisConfig.java b/src/main/java/jasper/config/RedisConfig.java index 15a1907a..b442064c 100644 --- a/src/main/java/jasper/config/RedisConfig.java +++ b/src/main/java/jasper/config/RedisConfig.java @@ -23,7 +23,6 @@ import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.ExecutorChannel; import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.integration.util.CallerBlocksPolicy; import org.springframework.messaging.Message; @@ -164,7 +163,7 @@ public TaskExecutor taskExecutor() { @Bean public IntegrationFlow redisPublishCursorFlow() { - return IntegrationFlows + return IntegrationFlow .from(cursorTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -182,7 +181,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeCursorFlow() { - return IntegrationFlows.from(cursorRedisChannel()) + return IntegrationFlow + .from(cursorRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(cursorRxChannel) .get(); @@ -203,7 +203,7 @@ public RedisMessageListenerContainer redisCursorRxAdapter(RedisConnectionFactory @Bean public IntegrationFlow redisPublishRefFlow() { - return IntegrationFlows + return IntegrationFlow .from(refTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -226,7 +226,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeRefFlow() { - return IntegrationFlows.from(refRedisChannel()) + return IntegrationFlow + .from(refRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(refRxChannel) .get(); @@ -251,7 +252,7 @@ public RedisMessageListenerContainer redisRefRxAdapter(RedisConnectionFactory re @Bean public IntegrationFlow redisPublishTagFlow() { - return IntegrationFlows + return IntegrationFlow .from(tagTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -269,7 +270,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeTagFlow() { - return IntegrationFlows.from(tagRedisChannel()) + return IntegrationFlow + .from(tagRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(tagRxChannel) .get(); @@ -291,7 +293,7 @@ public RedisMessageListenerContainer redisTagRxAdapter(RedisConnectionFactory re @Bean public IntegrationFlow redisPublishResponseFlow() { - return IntegrationFlows + return IntegrationFlow .from(responseTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -309,7 +311,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeResponseFlow() { - return IntegrationFlows.from(responseRedisChannel()) + return IntegrationFlow + .from(responseRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(responseRxChannel) .get(); @@ -331,7 +334,7 @@ public RedisMessageListenerContainer redisResponseRxAdapter(RedisConnectionFacto @Bean public IntegrationFlow redisPublishUserFlow() { - return IntegrationFlows + return IntegrationFlow .from(userTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -354,7 +357,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeUserFlow() { - return IntegrationFlows.from(userRedisChannel()) + return IntegrationFlow + .from(userRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(userRxChannel) .get(); @@ -380,7 +384,7 @@ public RedisMessageListenerContainer redisUserRxAdapter(RedisConnectionFactory r @Bean public IntegrationFlow redisPublishExtFlow() { - return IntegrationFlows + return IntegrationFlow .from(extTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -403,7 +407,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeExtFlow() { - return IntegrationFlows.from(extRedisChannel()) + return IntegrationFlow + .from(extRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(extRxChannel) .get(); @@ -429,7 +434,7 @@ public RedisMessageListenerContainer redisExtRxAdapter(RedisConnectionFactory re @Bean public IntegrationFlow redisPublishPluginFlow() { - return IntegrationFlows + return IntegrationFlow .from(pluginTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -452,7 +457,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribePluginFlow() { - return IntegrationFlows.from(pluginRedisChannel()) + return IntegrationFlow + .from(pluginRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(pluginRxChannel) .get(); @@ -478,7 +484,7 @@ public RedisMessageListenerContainer redisPluginRxAdapter(RedisConnectionFactory @Bean public IntegrationFlow redisPublishTemplateFlow() { - return IntegrationFlows + return IntegrationFlow .from(templateTxChannel) .handle(new CustomPublishingMessageHandler() { @Override @@ -501,7 +507,8 @@ protected byte[] getMessage(Message message) { @Bean public IntegrationFlow redisSubscribeTemplateFlow() { - return IntegrationFlows.from(templateRedisChannel()) + return IntegrationFlow + .from(templateRedisChannel()) .channel(new ExecutorChannel(taskExecutor)) .channel(templateRxChannel) .get(); diff --git a/src/main/java/jasper/config/SecurityConfiguration.java b/src/main/java/jasper/config/SecurityConfiguration.java index ab225ad5..b38b5b92 100644 --- a/src/main/java/jasper/config/SecurityConfiguration.java +++ b/src/main/java/jasper/config/SecurityConfiguration.java @@ -1,5 +1,6 @@ package jasper.config; +import jakarta.annotation.PostConstruct; import jasper.component.ConfigCache; import jasper.security.jwt.JWTConfigurer; import jasper.security.jwt.TokenProvider; @@ -9,13 +10,13 @@ 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; import org.springframework.context.annotation.Import; -import org.springframework.http.HttpMethod; import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; @@ -23,11 +24,11 @@ import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; import org.springframework.web.context.annotation.ApplicationScope; import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport; -import javax.annotation.PostConstruct; import java.util.Arrays; import java.util.List; @@ -40,21 +41,19 @@ import static org.apache.commons.lang3.ArrayUtils.isEmpty; import static org.apache.commons.lang3.StringUtils.isNotBlank; +@Configuration @EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) +@EnableMethodSecurity @Import(SecurityProblemSupport.class) public class SecurityConfiguration { private final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class); @Autowired - Props props; - + Props props; @Autowired ConfigCache configs; - @Autowired - SecurityProblemSupport problemSupport; - + SecurityProblemSupport problemSupport; @Autowired TokenProvider tokenProvider; @@ -104,35 +103,28 @@ private boolean profile(String profile) { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // @formatter:off http - .exceptionHandling() - .authenticationEntryPoint(problemSupport) - .accessDeniedHandler(problemSupport) - .and() - .headers() - .contentSecurityPolicy(props.getSecurity().getContentSecurityPolicy()) - .and() - .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN) - .and() - .permissionsPolicy().policy("camera=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=()") - .and() - .frameOptions() - .deny() - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() + .exceptionHandling(e -> e + .authenticationEntryPoint(problemSupport) + .accessDeniedHandler(problemSupport) + ) + .headers(h -> h + .contentSecurityPolicy(csp -> csp + .policyDirectives(props.getSecurity().getContentSecurityPolicy())) + .referrerPolicy(r -> r.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)) + .frameOptions(f -> f.sameOrigin()) + .permissionsPolicy(p -> p.policy("camera=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=()")) + ) + .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .apply(securityConfigurerAdapter()) - .and() - .authorizeRequests() - .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() - .and() - .headers() - .frameOptions() - .sameOrigin() - .and() - .csrf() + .and() + .authorizeHttpRequests(r -> r + .requestMatchers("/api/**").permitAll() + ) + .csrf(c -> c + .csrfTokenRequestHandler(csrfRequestHandler()) .csrfTokenRepository(csrfTokenRepository()) - .ignoringAntMatchers("/pub/api/**") // Public API + .ignoringRequestMatchers("/pub/api/**") // Public API + ) ; // @formatter:on return http.build(); } @@ -156,6 +148,15 @@ CsrfTokenRepository csrfTokenRepository() { return r; } + @Bean + CsrfTokenRequestAttributeHandler csrfRequestHandler() { + CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler(); + // TODO: CSRF BREACH: https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html + // Opt out of deferred csrf token loading + requestHandler.setCsrfRequestAttributeName(null); + return requestHandler; + } + @Bean @ApplicationScope public RoleHierarchy roleHierarchy() { diff --git a/src/main/java/jasper/config/SingleNodeConfig.java b/src/main/java/jasper/config/SingleNodeConfig.java index 89b95450..db0e24c6 100644 --- a/src/main/java/jasper/config/SingleNodeConfig.java +++ b/src/main/java/jasper/config/SingleNodeConfig.java @@ -8,7 +8,6 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.integration.channel.ExecutorChannel; import org.springframework.integration.dsl.IntegrationFlow; -import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.messaging.MessageChannel; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -86,65 +85,73 @@ public TaskExecutor taskExecutor() { @Bean public IntegrationFlow directCursorFlow() { - return IntegrationFlows.from(cursorTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(cursorRxChannel) - .get(); + return IntegrationFlow + .from(cursorTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(cursorRxChannel) + .get(); } @Bean public IntegrationFlow directRefFlow() { - return IntegrationFlows.from(refTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(refRxChannel) - .get(); + return IntegrationFlow + .from(refTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(refRxChannel) + .get(); } @Bean public IntegrationFlow directTagFlow() { - return IntegrationFlows.from(tagTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(tagRxChannel) - .get(); + return IntegrationFlow + .from(tagTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(tagRxChannel) + .get(); } @Bean public IntegrationFlow directResponseFlow() { - return IntegrationFlows.from(responseTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(responseRxChannel) - .get(); + return IntegrationFlow + .from(responseTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(responseRxChannel) + .get(); } @Bean public IntegrationFlow directUserFlow() { - return IntegrationFlows.from(userTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(userRxChannel) - .get(); + return IntegrationFlow + .from(userTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(userRxChannel) + .get(); } @Bean public IntegrationFlow directExtFlow() { - return IntegrationFlows.from(extTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(extRxChannel) - .get(); + return IntegrationFlow + .from(extTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(extRxChannel) + .get(); } @Bean public IntegrationFlow directPluginFlow() { - return IntegrationFlows.from(pluginTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(pluginRxChannel) - .get(); + return IntegrationFlow + .from(pluginTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(pluginRxChannel) + .get(); } @Bean public IntegrationFlow directTemplateFlow() { - return IntegrationFlows.from(templateTxChannel) - .channel(new ExecutorChannel(taskExecutor)) - .channel(templateRxChannel) - .get(); + return IntegrationFlow + .from(templateTxChannel) + .channel(new ExecutorChannel(taskExecutor)) + .channel(templateRxChannel) + .get(); } } diff --git a/src/main/java/jasper/config/WebConfigurer.java b/src/main/java/jasper/config/WebConfigurer.java index 909a361c..1228aedf 100644 --- a/src/main/java/jasper/config/WebConfigurer.java +++ b/src/main/java/jasper/config/WebConfigurer.java @@ -1,5 +1,7 @@ package jasper.config; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.server.WebServerFactory; @@ -14,8 +16,6 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; diff --git a/src/main/java/jasper/config/WebSocketConfig.java b/src/main/java/jasper/config/WebSocketConfig.java index 5329899b..5f4cf5b4 100644 --- a/src/main/java/jasper/config/WebSocketConfig.java +++ b/src/main/java/jasper/config/WebSocketConfig.java @@ -1,5 +1,6 @@ package jasper.config; +import jakarta.servlet.http.HttpServletRequest; import jasper.security.Auth; import jasper.security.jwt.TokenProvider; import jasper.security.jwt.TokenProviderImplDefault; @@ -38,7 +39,6 @@ import org.springframework.web.socket.server.HandshakeInterceptor; import org.springframework.web.socket.server.support.DefaultHandshakeHandler; -import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.security.Principal; import java.util.ArrayList; diff --git a/src/main/java/jasper/domain/AbstractAuditingEntity.java b/src/main/java/jasper/domain/AbstractAuditingEntity.java index 6c664f6b..8d2ce527 100644 --- a/src/main/java/jasper/domain/AbstractAuditingEntity.java +++ b/src/main/java/jasper/domain/AbstractAuditingEntity.java @@ -1,15 +1,15 @@ package jasper.domain; import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.Column; -import javax.persistence.EntityListeners; -import javax.persistence.MappedSuperclass; import java.io.Serializable; import java.time.Instant; diff --git a/src/main/java/jasper/domain/Ext.java b/src/main/java/jasper/domain/Ext.java index 4e474c95..a26f6e30 100644 --- a/src/main/java/jasper/domain/Ext.java +++ b/src/main/java/jasper/domain/Ext.java @@ -2,25 +2,23 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import com.vladmihalcea.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; import jasper.domain.proj.HasOrigin; import jasper.domain.proj.Tag; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; import org.hibernate.validator.constraints.Length; import org.springframework.data.annotation.LastModifiedDate; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; import java.time.Instant; import java.util.Objects; @@ -28,9 +26,6 @@ @Getter @Setter @IdClass(TagId.class) -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonType.class) -}) public class Ext implements Tag { public static final int NAME_LEN = 512; @@ -54,7 +49,7 @@ public class Ext implements Tag { @Length(max = NAME_LEN) private String name; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private JsonNode config; diff --git a/src/main/java/jasper/domain/Plugin.java b/src/main/java/jasper/domain/Plugin.java index 20c82e1e..78a7637b 100644 --- a/src/main/java/jasper/domain/Plugin.java +++ b/src/main/java/jasper/domain/Plugin.java @@ -3,7 +3,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.vladmihalcea.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; import jasper.domain.proj.HasOrigin; import jasper.domain.proj.Tag; import jasper.domain.validator.SchemaValid; @@ -11,18 +16,11 @@ import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; import org.hibernate.validator.constraints.Length; import org.springframework.data.annotation.LastModifiedDate; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; import java.time.Instant; import java.util.Objects; @@ -32,9 +30,6 @@ @Getter @Setter @IdClass(TagId.class) -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonType.class) -}) public class Plugin implements Tag { public static final String REGEX = "[_+]?plugin(?:/[a-z0-9]+(?:[./][a-z0-9]+)*)?"; public static final String QTAG_REGEX = REGEX + HasOrigin.REGEX; @@ -60,15 +55,15 @@ public class Plugin implements Tag { @Length(max = NAME_LEN) private String name; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private ObjectNode config; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private JsonNode defaults; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") @SchemaValid private ObjectNode schema; diff --git a/src/main/java/jasper/domain/Ref.java b/src/main/java/jasper/domain/Ref.java index 2ebb5a67..393cb873 100644 --- a/src/main/java/jasper/domain/Ref.java +++ b/src/main/java/jasper/domain/Ref.java @@ -3,8 +3,13 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.vladmihalcea.hibernate.type.json.JsonType; -import com.vladmihalcea.hibernate.type.search.PostgreSQLTSVectorType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import jasper.domain.proj.HasOrigin; import jasper.domain.proj.HasTags; import jasper.domain.proj.Tag; @@ -12,19 +17,11 @@ import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; import org.hibernate.validator.constraints.Length; import org.springframework.data.annotation.CreatedDate; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -40,10 +37,6 @@ @Getter @Setter @IdClass(RefId.class) -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonType.class), - @TypeDef(name = "tsvector", typeClass = PostgreSQLTSVectorType.class) -}) public class Ref implements HasTags { public static final String REGEX = "^[^:/?#]+:(?://[^/?#]*)?[^?#]*(?:\\?[^#]*)?(?:#.*)?"; public static final String SCHEME_REGEX = "^[^:/?#]+:"; @@ -68,23 +61,23 @@ public class Ref implements HasTags { private String comment; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = TAG_LEN) @Pattern(regexp = Tag.REGEX) String> tags; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = URL_LEN) @Pattern(regexp = REGEX) String> sources; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = URL_LEN) @Pattern(regexp = REGEX) String> alternateUrls; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private ObjectNode plugins; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private Metadata metadata; @@ -135,10 +128,6 @@ public class Ref implements HasTags { private Instant modified = Instant.now(); - @Type(type = "tsvector") - @Column(updatable = false, insertable = false) - private String textsearchEn; - public boolean hasPluginResponse(String tag) { // TODO: group plugin responses by origin if (metadata == null) return false; diff --git a/src/main/java/jasper/domain/Template.java b/src/main/java/jasper/domain/Template.java index ddc2c6ab..0244b6c0 100644 --- a/src/main/java/jasper/domain/Template.java +++ b/src/main/java/jasper/domain/Template.java @@ -3,7 +3,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.vladmihalcea.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.validation.constraints.Pattern; import jasper.domain.proj.HasOrigin; import jasper.domain.proj.Tag; import jasper.domain.validator.SchemaValid; @@ -11,17 +15,11 @@ import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; import org.hibernate.validator.constraints.Length; import org.springframework.data.annotation.LastModifiedDate; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.validation.constraints.Pattern; import java.time.Instant; import java.util.Objects; @@ -31,9 +29,6 @@ @Getter @Setter @IdClass(TagId.class) -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonType.class) -}) public class Template implements Tag { public static final String REGEX = "(?:_?[a-z0-9]+(?:[./][a-z0-9]+)*)?"; public static final String QTAG_REGEX = REGEX + HasOrigin.REGEX; @@ -58,15 +53,15 @@ public class Template implements Tag { @Length(max = NAME_LEN) private String name; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private JsonNode config; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private JsonNode defaults; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") @SchemaValid private ObjectNode schema; diff --git a/src/main/java/jasper/domain/User.java b/src/main/java/jasper/domain/User.java index 9cc95bf2..f5bbd9a7 100644 --- a/src/main/java/jasper/domain/User.java +++ b/src/main/java/jasper/domain/User.java @@ -1,7 +1,14 @@ package jasper.domain; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.vladmihalcea.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; import jasper.domain.proj.HasOrigin; import jasper.domain.proj.Tag; import lombok.AccessLevel; @@ -9,20 +16,11 @@ import lombok.Setter; import org.apache.commons.compress.utils.Sets; import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; import org.hibernate.validator.constraints.Length; import org.springframework.data.annotation.LastModifiedDate; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.Table; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; import java.time.Instant; import java.util.List; import java.util.Objects; @@ -40,9 +38,6 @@ @Setter @IdClass(TagId.class) @Table(name = "users") -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonType.class) -}) public class User implements Tag { public static final String REGEX = "[_+]user(?:/[a-z0-9]+(?:[./][a-z0-9]+)*)?"; public static final String ROLE_REGEX = "\\w*"; @@ -80,19 +75,19 @@ public class User implements Tag { @Length(max = NAME_LEN) private String name; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = TAG_LEN) @Pattern(regexp = Tag.REGEX) String> readAccess; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = TAG_LEN) @Pattern(regexp = Tag.REGEX) String> writeAccess; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = TAG_LEN) @Pattern(regexp = Tag.REGEX) String> tagReadAccess; - @Type(type = "json") + @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private List<@Length(max = TAG_LEN) @Pattern(regexp = Tag.REGEX) String> tagWriteAccess; diff --git a/src/main/java/jasper/domain/validator/SchemaValid.java b/src/main/java/jasper/domain/validator/SchemaValid.java index 08823032..8eef73ef 100644 --- a/src/main/java/jasper/domain/validator/SchemaValid.java +++ b/src/main/java/jasper/domain/validator/SchemaValid.java @@ -1,7 +1,8 @@ package jasper.domain.validator; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; diff --git a/src/main/java/jasper/domain/validator/SchemaValidator.java b/src/main/java/jasper/domain/validator/SchemaValidator.java index bbdad470..0842d9c3 100644 --- a/src/main/java/jasper/domain/validator/SchemaValidator.java +++ b/src/main/java/jasper/domain/validator/SchemaValidator.java @@ -4,9 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.jsontypedef.jtd.InvalidSchemaException; import com.jsontypedef.jtd.Schema; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class SchemaValidator implements ConstraintValidator { public static final ObjectMapper mapper = new ObjectMapper(); diff --git a/src/main/java/jasper/repository/RefRepository.java b/src/main/java/jasper/repository/RefRepository.java index d63a6718..9255724c 100644 --- a/src/main/java/jasper/repository/RefRepository.java +++ b/src/main/java/jasper/repository/RefRepository.java @@ -1,6 +1,5 @@ package jasper.repository; -import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import jasper.domain.Metadata; import jasper.domain.Ref; @@ -47,9 +46,9 @@ int optimisticUpdate( String origin, String title, String comment, - ArrayNode tags, - ArrayNode sources, - ArrayNode alternateUrls, + List tags, + List sources, + List alternateUrls, ObjectNode plugins, Metadata metadata, Instant published, diff --git a/src/main/java/jasper/repository/StreamMixin.java b/src/main/java/jasper/repository/StreamMixin.java index 783b51dc..28f7a234 100644 --- a/src/main/java/jasper/repository/StreamMixin.java +++ b/src/main/java/jasper/repository/StreamMixin.java @@ -1,31 +1,28 @@ package jasper.repository; +import jakarta.persistence.QueryHint; import org.springframework.data.jpa.repository.QueryHints; -import javax.persistence.QueryHint; import java.time.Instant; import java.util.stream.Stream; -import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE; -import static org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE; -import static org.hibernate.jpa.QueryHints.HINT_PASS_DISTINCT_THROUGH; -import static org.hibernate.jpa.QueryHints.HINT_READONLY; +import static org.hibernate.jpa.AvailableHints.HINT_CACHEABLE; +import static org.hibernate.jpa.AvailableHints.HINT_FETCH_SIZE; +import static org.hibernate.jpa.AvailableHints.HINT_READ_ONLY; public interface StreamMixin { @QueryHints(value = { @QueryHint(name = HINT_FETCH_SIZE, value = "500"), @QueryHint(name = HINT_CACHEABLE, value = "false"), - @QueryHint(name = HINT_READONLY, value = "true"), - @QueryHint(name = HINT_PASS_DISTINCT_THROUGH, value = "false") + @QueryHint(name = HINT_READ_ONLY, value = "true") }) Stream streamAllByOriginAndModifiedGreaterThanEqualOrderByModifiedDesc(String origin, Instant newerThan); @QueryHints(value = { @QueryHint(name = HINT_FETCH_SIZE, value = "500"), @QueryHint(name = HINT_CACHEABLE, value = "false"), - @QueryHint(name = HINT_READONLY, value = "true"), - @QueryHint(name = HINT_PASS_DISTINCT_THROUGH, value = "false") + @QueryHint(name = HINT_READ_ONLY, value = "true") }) Stream streamAllByOriginOrderByModifiedDesc(String origin); } diff --git a/src/main/java/jasper/repository/TemplateRepository.java b/src/main/java/jasper/repository/TemplateRepository.java index 6ddf9d75..a81c8932 100644 --- a/src/main/java/jasper/repository/TemplateRepository.java +++ b/src/main/java/jasper/repository/TemplateRepository.java @@ -67,7 +67,7 @@ AND COALESCE(CAST(jsonb_object_field(t.config, 'disabled') as boolean), false) = OR t.tag = :tag OR (:tag LIKE '+%' AND concat('+', t.tag) = :tag) OR locate(concat(t.tag, '/'), :tag) = 1 - OR (:tag LIKE '\\_%' AND locate(concat(t.tag, '/'), :tag) = 2) + OR (:tag LIKE '\\_%' ESCAPE '\\' AND locate(concat(t.tag, '/'), :tag) = 2) OR (:tag LIKE '+%' AND locate(concat(t.tag, '/'), :tag) = 2)) ORDER BY t.levels ASC""") List