diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0783f2238..01e2b63c4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,7 +23,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Install Yarn run: npm install --global yarn - uses: actions/checkout@v2 diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index c584e303f..cec6b01cf 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -6,11 +6,9 @@ ENV DOCKER_BUMP=2 USER gitpod RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh \ - # Install Java 18 for the Java extension to function properly - && sdk install java 18.0.1.1-open \ - && sdk install java 11.0.2-open" + && sdk install java 17.0.7-tem" -RUN curl https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.11.0-linux-x86_64.tar.gz --output elasticsearch-linux-x86_64.tar.gz \ +RUN curl https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.7.1-linux-x86_64.tar.gz --output elasticsearch-linux-x86_64.tar.gz \ && tar -xzf elasticsearch-linux-x86_64.tar.gz \ && rm elasticsearch-linux-x86_64.tar.gz -ENV ES_HOME="$HOME/elasticsearch-7.11.0" +ENV ES_HOME="$HOME/elasticsearch-8.7.1" diff --git a/.gitpod.yml b/.gitpod.yml index 032b309e3..fbfe80b3c 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -39,7 +39,7 @@ tasks: command: | if [[ $NPM_TOKEN ]]; then echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc; fi # Start Elasticsearch as background process - $ES_HOME/bin/elasticsearch -d -p $ES_HOME/pid -Ediscovery.type=single-node -Expack.ml.enabled=false + $ES_HOME/bin/elasticsearch -d -p $ES_HOME/pid -Ediscovery.type=single-node -Expack.ml.enabled=false -Expack.security.enabled=false gp ports await 9200 # Start the server application cd server diff --git a/doc/development.md b/doc/development.md index 2127d8efe..cd2c60685 100644 --- a/doc/development.md +++ b/doc/development.md @@ -40,9 +40,13 @@ To get started quickly, it is recommended to use Gitpod as default with the deve - [https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl) -- Set up JDK 11 - - - sudo apt install onpenjdk-11-jdk +- Set up JDK 17 + - sudo apt install -y wget apt-transport-https + - mkdir -p /etc/apt/keyrings + - wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | tee /etc/apt/keyrings/adoptium.asc + - echo "deb [signed-by=/etc/apt/keyrings/adoptium.asc] https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list + - sudo apt update + - sudo apt install temurin-17-jdk - Install docker @@ -74,15 +78,15 @@ To get started quickly, it is recommended to use Gitpod as default with the deve - Make sure the correct Java version is being used - - Download Java 11 if you don't have it already + - Download Java 17 if you don't have it already: https://adoptium.net/temurin/releases/ - Run the command `/usr/libexec/java_home –V` to see your matching Java virtual machines - - Pick Java 11 accordingly + - Pick Java 17 accordingly - - export JAVA_HOME='/usr/libexec/java_home –v 11.0.18' + - export JAVA_HOME='/usr/libexec/java_home –v 17.0.7+7' - - Run `java –version` to check if Java 11 is indeed being used + - Run `java –version` to check if Java 17 is indeed being used - https://stackoverflow.com/questions/21964709/how-to-set-or-change-the-default-java-jdk-version-on-macos diff --git a/server/Dockerfile b/server/Dockerfile index 384df8e34..36762f23b 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,4 +1,4 @@ -FROM gradle:jdk11 as builder +FROM gradle:jdk17 as builder # Copy sources WORKDIR /home/gradle @@ -10,7 +10,7 @@ COPY --chown=gradle:gradle src ./src/ RUN ./gradlew --no-daemon assemble -FROM openjdk:11.0.7-jdk +FROM eclipse-temurin:17.0.7_7-jdk # Create user openvsx and set up home directory RUN groupadd -r openvsx && useradd --no-log-init -r -g openvsx openvsx diff --git a/server/build.gradle b/server/build.gradle index e39e70c5f..bfd121dba 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -3,13 +3,13 @@ buildscript { mavenCentral() } dependencies { - classpath "org.hibernate:hibernate-gradle-plugin:5.4.22.Final" + classpath "org.hibernate.orm:hibernate-gradle-plugin:6.2.2.Final" } } plugins { id 'nu.studer.jooq' version '6.0.1' id 'de.undercouch.download' version '4.1.1' - id 'org.springframework.boot' version '2.7.1' + id 'org.springframework.boot' version '3.1.0' id 'io.spring.dependency-management' version '1.1.0' id 'io.gatling.gradle' version '3.6.1' id 'java' @@ -18,22 +18,26 @@ apply plugin: 'org.hibernate.orm' def jooqSrcDir = 'src/main/jooq-gen' def versions = [ - java: '11', - flyway: '7.3.1', - springdoc: '1.6.9', - spdx: '2.2.4', - gcloud: '1.113.4', - azure: '12.9.0', - guava: '28.2-jre', + java: '17', + flyway: '9.19.1', + springdoc: '2.1.0', + spdx: '2.2.8', + gcloud: '2.22.3', + azure: '12.18.0', + guava: '30.0-jre', junit: '5.7.1', testcontainers: '1.15.2', - jackson: '2.12.5', - woodstox: '6.2.4', - jobrunr: '5.1.2', - bucket4j: '0.4.0', - ehcache: '3.10.0', + jackson: '2.15.2', + woodstox: '6.4.0', + jobrunr: '6.2.0', + bucket4j: '0.9.0', + ehcache: '3.10.8', tika: '2.6.0', - bouncycastle: '1.69' + bouncycastle: '1.69', + commons_lang3: '3.12.0', + httpclient5: '5.2.1', + jaxb_api: '2.3.1', + jaxb_impl: '2.3.8' ] ext['junit-jupiter.version'] = versions.junit sourceCompatibility = versions.java @@ -75,11 +79,11 @@ dependencies { implementation "org.bouncycastle:bcpkix-jdk15on:${versions.bouncycastle}" implementation "org.ehcache:ehcache:${versions.ehcache}" implementation "com.giffing.bucket4j.spring.boot.starter:bucket4j-spring-boot-starter:${versions.bucket4j}" - implementation "org.jobrunr:jobrunr-spring-boot-starter:${versions.jobrunr}" + implementation "org.jobrunr:jobrunr-spring-boot-3-starter:${versions.jobrunr}" implementation "org.flywaydb:flyway-core:${versions.flyway}" implementation "com.google.cloud:google-cloud-storage:${versions.gcloud}" implementation "com.azure:azure-storage-blob:${versions.azure}" - implementation "org.springdoc:springdoc-openapi-ui:${versions.springdoc}" + implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:${versions.springdoc}" implementation "com.google.guava:guava:${versions.guava}" implementation "com.fasterxml.jackson.core:jackson-core:${versions.jackson}" implementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" @@ -87,6 +91,10 @@ dependencies { implementation "com.fasterxml.jackson.module:jackson-module-jaxb-annotations:${versions.jackson}" implementation "com.fasterxml.woodstox:woodstox-core:${versions.woodstox}" implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${versions.jackson}" + implementation "javax.xml.bind:jaxb-api:${versions.jaxb_api}" + implementation "com.sun.xml.bind:jaxb-impl:${versions.jaxb_impl}" + implementation "org.apache.commons:commons-lang3:${versions.commons_lang3}" + implementation "org.apache.httpcomponents.client5:httpclient5:${versions.httpclient5}" implementation "org.apache.tika:tika-core:${versions.tika}" implementation("org.spdx:spdx-tools:${versions.spdx}") { exclude group: 'net.sf.saxon' @@ -109,13 +117,6 @@ dependencies { testRuntimeOnly "org.testcontainers:postgresql:${versions.testcontainers}" } -hibernate { - enhance { - enableLazyInitialization = true - enableDirtyTracking = true - } -} - jooq { // use jOOQ version defined in Spring Boot version = dependencyManagement.importedProperties['jooq.version'] diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties index 84d1f85fd..fae08049a 100644 --- a/server/gradle/wrapper/gradle-wrapper.properties +++ b/server/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew index 1b6c78733..2f856aa37 100755 --- a/server/gradlew +++ b/server/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright � 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions �$var�, �${var}�, �${var:-default}�, �${var+SET}�, +# �${var#prefix}�, �${var%suffix}�, and �$( cmd )�; +# * compound commands having a testable exit status, especially �case�; +# * various built-in commands including �command�, �set�, and �ulimit�. # # Important for patching: # diff --git a/server/src/dev/resources/application.yml b/server/src/dev/resources/application.yml index 6bdeac926..624660c2a 100644 --- a/server/src/dev/resources/application.yml +++ b/server/src/dev/resources/application.yml @@ -65,6 +65,7 @@ management: springdoc: swagger-ui: + path: /swagger-ui docExpansion: list operationsSorter: alpha supportedSubmitMethods: @@ -93,7 +94,7 @@ bucket4j: Access-Control-Allow-Origin: '*' Access-Control-Expose-Headers: X-Rate-Limit-Retry-After-Seconds, X-Rate-Limit-Remaining rate-limits: - - expression: getParameter("token") + - cache-key: getParameter("token") bandwidths: - capacity: 15 time: 1 @@ -104,7 +105,7 @@ bucket4j: Access-Control-Allow-Origin: '*' Access-Control-Expose-Headers: X-Rate-Limit-Retry-After-Seconds, X-Rate-Limit-Remaining rate-limits: - - expression: getRemoteAddr() + - cache-key: getRemoteAddr() bandwidths: - capacity: 75 time: 1 @@ -115,7 +116,7 @@ bucket4j: Access-Control-Allow-Origin: '*' Access-Control-Expose-Headers: X-Rate-Limit-Retry-After-Seconds, X-Rate-Limit-Remaining rate-limits: - - expression: getRemoteAddr() + - cache-key: getRemoteAddr() bandwidths: - capacity: 15 time: 1 diff --git a/server/src/main/java/org/eclipse/openvsx/ExtensionProcessor.java b/server/src/main/java/org/eclipse/openvsx/ExtensionProcessor.java index b9bcc02b6..228905eb1 100644 --- a/server/src/main/java/org/eclipse/openvsx/ExtensionProcessor.java +++ b/server/src/main/java/org/eclipse/openvsx/ExtensionProcessor.java @@ -15,10 +15,10 @@ import com.fasterxml.jackson.databind.node.MissingNode; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.ExtensionVersion; import org.eclipse.openvsx.entities.FileResource; import org.eclipse.openvsx.util.*; -import org.elasticsearch.common.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.util.Pair; @@ -273,7 +273,7 @@ private List getTags() { } private List asStringList(String value, String sep){ - if (Strings.isNullOrEmpty(value)){ + if (StringUtils.isEmpty(value)){ return new ArrayList<>(); } @@ -410,7 +410,7 @@ public FileResource getLicense(ExtensionVersion extVersion) { license.setExtension(extVersion); license.setType(FileResource.LICENSE); // Parse specifications in the form "SEE MIT LICENSE IN LICENSE.txt" - if (!Strings.isNullOrEmpty(extVersion.getLicense())) { + if (!StringUtils.isEmpty(extVersion.getLicense())) { var matcher = LICENSE_PATTERN.matcher(extVersion.getLicense()); if (matcher.find()) { extVersion.setLicense(matcher.group("license")); @@ -438,7 +438,7 @@ public FileResource getLicense(ExtensionVersion extVersion) { } private void detectLicense(byte[] content, ExtensionVersion extVersion) { - if (Strings.isNullOrEmpty(extVersion.getLicense())) { + if (StringUtils.isEmpty(extVersion.getLicense())) { var detection = new LicenseDetection(); extVersion.setLicense(detection.detectLicense(content)); } diff --git a/server/src/main/java/org/eclipse/openvsx/ExtensionService.java b/server/src/main/java/org/eclipse/openvsx/ExtensionService.java index 572e3e285..1caa5d052 100644 --- a/server/src/main/java/org/eclipse/openvsx/ExtensionService.java +++ b/server/src/main/java/org/eclipse/openvsx/ExtensionService.java @@ -16,11 +16,10 @@ import java.time.LocalDateTime; import java.util.LinkedHashSet; -import javax.transaction.Transactional; -import javax.transaction.Transactional.TxType; - -import com.google.common.base.Strings; +import jakarta.transaction.Transactional; +import jakarta.transaction.Transactional.TxType; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.cache.CacheService; import org.eclipse.openvsx.entities.*; import org.eclipse.openvsx.publish.PublishExtensionVersionHandler; @@ -102,7 +101,7 @@ private TempFile createExtensionFile(InputStream content) { } private void checkLicense(ExtensionVersion extVersion, FileResource license) { - if (Strings.isNullOrEmpty(extVersion.getLicense()) && (license == null || !license.getType().equals(FileResource.LICENSE))) { + if (StringUtils.isEmpty(extVersion.getLicense()) && (license == null || !license.getType().equals(FileResource.LICENSE))) { throw new ErrorResultException("This extension cannot be accepted because it has no license."); } } diff --git a/server/src/main/java/org/eclipse/openvsx/ExtensionValidator.java b/server/src/main/java/org/eclipse/openvsx/ExtensionValidator.java index d29d70d42..c542fc7c3 100644 --- a/server/src/main/java/org/eclipse/openvsx/ExtensionValidator.java +++ b/server/src/main/java/org/eclipse/openvsx/ExtensionValidator.java @@ -9,7 +9,7 @@ ********************************************************************************/ package org.eclipse.openvsx; -import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.apache.tika.Tika; import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MimeTypeException; @@ -48,7 +48,7 @@ public class ExtensionValidator { private final Pattern namePattern = Pattern.compile("[\\w\\-\\+\\$~]+"); public Optional validateNamespace(String namespace) { - if (Strings.isNullOrEmpty(namespace) || namespace.equals("-")) { + if (StringUtils.isEmpty(namespace) || namespace.equals("-")) { return Optional.of(new Issue("Namespace name must not be empty.")); } if (!namePattern.matcher(namespace).matches()) { @@ -102,7 +102,7 @@ public List validateNamespaceDetails(NamespaceDetailsJson json) { } public Optional validateExtensionName(String name) { - if (Strings.isNullOrEmpty(name)) { + if (StringUtils.isEmpty(name)) { return Optional.of(new Issue("Name must not be empty.")); } if (!namePattern.matcher(name).matches()) { @@ -156,7 +156,7 @@ public List validateMetadata(ExtensionVersion extVersion) { } private void checkVersion(String version, List issues) { - if (Strings.isNullOrEmpty(version)) { + if (StringUtils.isEmpty(version)) { issues.add(new Issue("Version must not be empty.")); return; } @@ -216,7 +216,7 @@ private void checkFieldSize(List values, int limit, String field, List isInvalid, String field, List issues, String allowedValues) { - if (Strings.isNullOrEmpty(value)) { + if (StringUtils.isEmpty(value)) { return; } if (isInvalid.test(value)) { @@ -226,7 +226,7 @@ private void checkInvalid(String value, Predicate isInvalid, String fiel } private void checkURL(String value, String field, List issues) { - if (Strings.isNullOrEmpty(value)) { + if (StringUtils.isEmpty(value)) { return; } if (isInvalidURL(value)) { @@ -235,14 +235,14 @@ private void checkURL(String value, String field, List issues) { } private boolean isInvalidURL(String value) { - if (Strings.isNullOrEmpty(value)) + if (StringUtils.isEmpty(value)) return true; if (value.startsWith("git+") && value.length() > 4) value = value.substring(4); try { var url = new URL(value); - return url.getProtocol().matches("http(s)?") && Strings.isNullOrEmpty(url.getHost()); + return url.getProtocol().matches("http(s)?") && StringUtils.isEmpty(url.getHost()); } catch (MalformedURLException exc) { return true; } diff --git a/server/src/main/java/org/eclipse/openvsx/LocalRegistryService.java b/server/src/main/java/org/eclipse/openvsx/LocalRegistryService.java index a3b0e6cc3..bcfefb34c 100644 --- a/server/src/main/java/org/eclipse/openvsx/LocalRegistryService.java +++ b/server/src/main/java/org/eclipse/openvsx/LocalRegistryService.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx; -import com.google.common.base.Strings; import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.cache.CacheService; import org.eclipse.openvsx.eclipse.EclipseService; import org.eclipse.openvsx.entities.*; @@ -36,8 +36,8 @@ import org.springframework.stereotype.Component; import org.springframework.web.server.ResponseStatusException; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.InputStream; import java.util.*; import java.util.stream.Collectors; @@ -268,21 +268,26 @@ public SearchResultJson search(ISearchService.Options options) { } var searchHits = search.search(options); - json.extensions = toSearchEntries(searchHits, options); - json.offset = options.requestedOffset; - json.totalSize = (int) searchHits.getTotalHits(); + if(searchHits.hasSearchHits()) { + json.extensions = toSearchEntries(searchHits, options); + json.offset = options.requestedOffset; + json.totalSize = (int) searchHits.getTotalHits(); + } else { + json.extensions = Collections.emptyList(); + } + return json; } @Override public QueryResultJson query(QueryRequest request) { - if (!Strings.isNullOrEmpty(request.extensionId)) { + if (!StringUtils.isEmpty(request.extensionId)) { var split = request.extensionId.split("\\."); if (split.length != 2 || split[0].isEmpty() || split[1].isEmpty()) throw new ErrorResultException("The 'extensionId' parameter must have the format 'namespace.extension'."); - if (!Strings.isNullOrEmpty(request.namespaceName) && !request.namespaceName.equals(split[0])) + if (!StringUtils.isEmpty(request.namespaceName) && !request.namespaceName.equals(split[0])) throw new ErrorResultException("Conflicting parameters 'extensionId' and 'namespaceName'"); - if (!Strings.isNullOrEmpty(request.extensionName) && !request.extensionName.equals(split[1])) + if (!StringUtils.isEmpty(request.extensionName) && !request.extensionName.equals(split[1])) throw new ErrorResultException("Conflicting parameters 'extensionId' and 'extensionName'"); request.namespaceName = split[0]; request.extensionName = split[1]; @@ -327,13 +332,13 @@ public QueryResultJson query(QueryRequest request) { @Override public QueryResultJson queryV2(QueryRequestV2 request) { - if (!Strings.isNullOrEmpty(request.extensionId)) { + if (!StringUtils.isEmpty(request.extensionId)) { var split = request.extensionId.split("\\."); if (split.length != 2 || split[0].isEmpty() || split[1].isEmpty()) throw new ErrorResultException("The 'extensionId' parameter must have the format 'namespace.extension'."); - if (!Strings.isNullOrEmpty(request.namespaceName) && !request.namespaceName.equals(split[0])) + if (!StringUtils.isEmpty(request.namespaceName) && !request.namespaceName.equals(split[0])) throw new ErrorResultException("Conflicting parameters 'extensionId' and 'namespaceName'"); - if (!Strings.isNullOrEmpty(request.extensionName) && !request.extensionName.equals(split[1])) + if (!StringUtils.isEmpty(request.extensionName) && !request.extensionName.equals(split[1])) throw new ErrorResultException("Conflicting parameters 'extensionId' and 'extensionName'"); request.namespaceName = split[0]; request.extensionName = split[1]; @@ -344,7 +349,7 @@ public QueryResultJson queryV2(QueryRequestV2 request) { request.targetPlatform = null; } // Revert to default includeAllVersions value when extensionVersion is set - if(!Strings.isNullOrEmpty(request.extensionVersion) && request.includeAllVersions.equals("true")) { + if(!StringUtils.isEmpty(request.extensionVersion) && request.includeAllVersions.equals("true")) { request.includeAllVersions = "links"; } @@ -712,26 +717,40 @@ public ResultJson deleteReview(String namespace, String extensionName) { return ResultJson.success("Deleted review for " + NamingUtil.toExtensionId(extension)); } - private Extension getExtension(SearchHit searchHit) { - var searchItem = searchHit.getContent(); - var extension = entityManager.find(Extension.class, searchItem.id); - if (extension == null || !extension.isActive()) { - extension = new Extension(); - extension.setId(searchItem.id); - search.removeSearchEntry(extension); - return null; + private List getExtensions(SearchHits searchHits) { + var ids = searchHits.stream() + .map(searchHit -> searchHit.getContent().id) + .collect(Collectors.toSet()); + + var extensions = new ArrayList<>(repositories.findExtensions(ids).toList()); + var extensionIds = extensions.stream() + .map(Extension::getId) + .collect(Collectors.toSet()); + + ids.removeAll(extensionIds); + if(!ids.isEmpty()) { + search.removeSearchEntries(ids); } - return extension; + var inactiveExtensions = extensions.stream() + .filter(extension -> !extension.isActive()) + .collect(Collectors.toList()); + + if(!inactiveExtensions.isEmpty()) { + var inactiveIds = inactiveExtensions.stream() + .map(Extension::getId) + .collect(Collectors.toList()); + + search.removeSearchEntries(inactiveIds); + extensions.removeAll(inactiveExtensions); + } + + return extensions; } private List toSearchEntries(SearchHits searchHits, ISearchService.Options options) { var serverUrl = UrlUtil.getBaseUrl(); - var extensions = searchHits.stream() - .map(this::getExtension) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - + var extensions = getExtensions(searchHits); var latestVersions = extensions.stream() .map(e -> { var latest = versions.getLatestTrxn(e, null, false, true); @@ -1005,8 +1024,7 @@ private boolean isVerified(ExtensionVersion extVersion) { } var namespace = extVersion.getExtension().getNamespace(); - return repositories.countMemberships(namespace, NamespaceMembership.ROLE_OWNER) > 0 - && repositories.countMemberships(user, namespace) > 0; + return repositories.isVerified(namespace, user); } private boolean isVerified(ExtensionVersion extVersion, Map> membershipsByNamespaceId) { diff --git a/server/src/main/java/org/eclipse/openvsx/RegistryAPI.java b/server/src/main/java/org/eclipse/openvsx/RegistryAPI.java index c148c3ca0..ae00d5f23 100644 --- a/server/src/main/java/org/eclipse/openvsx/RegistryAPI.java +++ b/server/src/main/java/org/eclipse/openvsx/RegistryAPI.java @@ -18,11 +18,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.SemanticVersion; import org.eclipse.openvsx.json.*; import org.eclipse.openvsx.search.ISearchService; import org.eclipse.openvsx.util.*; -import org.elasticsearch.common.Strings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.CacheControl; import org.springframework.http.HttpStatus; @@ -31,7 +31,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.io.InputStream; import java.net.URI; import java.util.ArrayList; @@ -1379,7 +1379,7 @@ public ResponseEntity createNamespace( if (namespace == null) { return ResponseEntity.ok(ResultJson.error("No JSON input.")); } - if (Strings.isNullOrEmpty(namespace.name)) { + if (StringUtils.isEmpty(namespace.name)) { return ResponseEntity.ok(ResultJson.error("Missing required property 'name'.")); } try { @@ -1462,7 +1462,7 @@ public ResponseEntity createNamespace( if (namespace == null) { return ResponseEntity.ok(ResultJson.error("No JSON input.")); } - if (Strings.isNullOrEmpty(namespace.name)) { + if (StringUtils.isEmpty(namespace.name)) { return ResponseEntity.ok(ResultJson.error("Missing required property 'name'.")); } try { diff --git a/server/src/main/java/org/eclipse/openvsx/RestTemplateConfig.java b/server/src/main/java/org/eclipse/openvsx/RestTemplateConfig.java index 84f7063ed..2ebd48aaa 100644 --- a/server/src/main/java/org/eclipse/openvsx/RestTemplateConfig.java +++ b/server/src/main/java/org/eclipse/openvsx/RestTemplateConfig.java @@ -9,9 +9,10 @@ * ****************************************************************************** */ package org.eclipse.openvsx; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.core5.util.Timeout; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; @@ -23,6 +24,8 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; +import java.util.concurrent.TimeUnit; + @Configuration public class RestTemplateConfig { @@ -141,9 +144,8 @@ public RestTemplate vsCodeIdRestTemplate( private HttpClientBuilder createHttpClientBuilder(HttpConnPoolConfig httpConnPoolConfig) { var requestConfig = RequestConfig.custom() - .setConnectionRequestTimeout(httpConnPoolConfig.getConnectionRequestTimeout()) - .setConnectTimeout(httpConnPoolConfig.getConnectTimeout()) - .setSocketTimeout(httpConnPoolConfig.getSocketTimeout()) + .setConnectionRequestTimeout(Timeout.of(httpConnPoolConfig.getConnectionRequestTimeout(), TimeUnit.MILLISECONDS)) + .setConnectTimeout(Timeout.of(httpConnPoolConfig.getConnectTimeout(), TimeUnit.MILLISECONDS)) .build(); return HttpClientBuilder .create() diff --git a/server/src/main/java/org/eclipse/openvsx/UpstreamProxyService.java b/server/src/main/java/org/eclipse/openvsx/UpstreamProxyService.java index e690b10e4..271dfb1dc 100644 --- a/server/src/main/java/org/eclipse/openvsx/UpstreamProxyService.java +++ b/server/src/main/java/org/eclipse/openvsx/UpstreamProxyService.java @@ -12,10 +12,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.adapter.ExtensionQueryResult; import org.eclipse.openvsx.json.*; import org.eclipse.openvsx.util.UrlUtil; -import org.elasticsearch.common.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -36,10 +36,10 @@ public class UpstreamProxyService { public NamespaceJson rewriteUrls(NamespaceJson json) { rewriteUrlMap(json.extensions); - if(!Strings.isNullOrEmpty(json.membersUrl)) { + if(!StringUtils.isEmpty(json.membersUrl)) { json.membersUrl = rewriteUrl(json.membersUrl); } - if(!Strings.isNullOrEmpty(json.roleUrl)) { + if(!StringUtils.isEmpty(json.roleUrl)) { json.roleUrl = rewriteUrl(json.roleUrl); } diff --git a/server/src/main/java/org/eclipse/openvsx/UpstreamRegistryService.java b/server/src/main/java/org/eclipse/openvsx/UpstreamRegistryService.java index b6ca88c3f..68c66e8f0 100644 --- a/server/src/main/java/org/eclipse/openvsx/UpstreamRegistryService.java +++ b/server/src/main/java/org/eclipse/openvsx/UpstreamRegistryService.java @@ -9,8 +9,7 @@ ********************************************************************************/ package org.eclipse.openvsx; -import com.google.common.base.Strings; - +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.json.*; import org.eclipse.openvsx.search.ISearchService; import org.eclipse.openvsx.util.NotFoundException; @@ -48,7 +47,7 @@ public class UpstreamRegistryService implements IExtensionRegistry { UrlConfigService urlConfigService; public boolean isValid() { - return !Strings.isNullOrEmpty(urlConfigService.getUpstreamUrl()); + return !StringUtils.isEmpty(urlConfigService.getUpstreamUrl()); } @Override @@ -273,7 +272,7 @@ public SearchResultJson search(ISearchService.Options options) { uriVariables.put("targetPlatform", options.targetPlatform); var queryString = uriVariables.entrySet().stream() - .filter(entry -> !Strings.isNullOrEmpty(entry.getValue())) + .filter(entry -> !StringUtils.isEmpty(entry.getValue())) .map(Map.Entry::getKey) .map(key -> key + "={" + key + "}") .collect(Collectors.joining("&")); @@ -310,7 +309,7 @@ public QueryResultJson query(QueryRequest request) { var queryString = queryParams.entrySet().stream() - .filter(entry -> !Strings.isNullOrEmpty(entry.getValue())) + .filter(entry -> !StringUtils.isEmpty(entry.getValue())) .map(Map.Entry::getKey) .map(key -> key + "={" + key + "}") .collect(Collectors.joining("&")); @@ -346,7 +345,7 @@ public QueryResultJson queryV2(QueryRequestV2 request) { queryParams.put("offset", String.valueOf(request.offset)); var queryString = queryParams.entrySet().stream() - .filter(entry -> !Strings.isNullOrEmpty(entry.getValue())) + .filter(entry -> !StringUtils.isEmpty(entry.getValue())) .map(Map.Entry::getKey) .map(key -> key + "={" + key + "}") .collect(Collectors.joining("&")); @@ -389,7 +388,7 @@ private void handleError(Throwable exc) throws RuntimeException { throw new NotFoundException(); else throw new ResponseStatusException(status, - "Upstream registry responded with status \"" + status.getReasonPhrase() + "\".", exc); + "Upstream registry responded with status \"" + exc.getMessage() + "\".", exc); } else if (exc.getCause() != null && exc.getCause() != exc) { handleError(exc.getCause()); } diff --git a/server/src/main/java/org/eclipse/openvsx/UserAPI.java b/server/src/main/java/org/eclipse/openvsx/UserAPI.java index 19573b595..468b4bdc9 100644 --- a/server/src/main/java/org/eclipse/openvsx/UserAPI.java +++ b/server/src/main/java/org/eclipse/openvsx/UserAPI.java @@ -16,7 +16,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.eclipse.openvsx.eclipse.EclipseService; import org.eclipse.openvsx.entities.NamespaceMembership; diff --git a/server/src/main/java/org/eclipse/openvsx/UserService.java b/server/src/main/java/org/eclipse/openvsx/UserService.java index 912ff8f74..046d2d712 100644 --- a/server/src/main/java/org/eclipse/openvsx/UserService.java +++ b/server/src/main/java/org/eclipse/openvsx/UserService.java @@ -29,8 +29,8 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.file.Files; diff --git a/server/src/main/java/org/eclipse/openvsx/adapter/LocalVSCodeService.java b/server/src/main/java/org/eclipse/openvsx/adapter/LocalVSCodeService.java index dab0f45bb..f69905f4c 100644 --- a/server/src/main/java/org/eclipse/openvsx/adapter/LocalVSCodeService.java +++ b/server/src/main/java/org/eclipse/openvsx/adapter/LocalVSCodeService.java @@ -12,6 +12,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.Extension; import org.eclipse.openvsx.entities.ExtensionVersion; import org.eclipse.openvsx.entities.FileResource; @@ -21,7 +22,6 @@ import org.eclipse.openvsx.search.SearchUtilService; import org.eclipse.openvsx.storage.StorageUtilService; import org.eclipse.openvsx.util.*; -import org.elasticsearch.common.Strings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; @@ -505,7 +505,7 @@ private ExtensionQueryResult.Extension toQueryExtension(Extension extension, Ext queryExt.publisher = new ExtensionQueryResult.Publisher(); queryExt.publisher.publisherId = namespace.getPublicId(); queryExt.publisher.publisherName = namespace.getName(); - queryExt.publisher.displayName = !Strings.isNullOrEmpty(namespace.getDisplayName()) ? namespace.getDisplayName() : namespace.getName(); + queryExt.publisher.displayName = !StringUtils.isEmpty(namespace.getDisplayName()) ? namespace.getDisplayName() : namespace.getName(); queryExt.tags = latest.getTags(); queryExt.releaseDate = TimeUtil.toUTCString(extension.getPublishedDate()); queryExt.publishedDate = TimeUtil.toUTCString(extension.getPublishedDate()); diff --git a/server/src/main/java/org/eclipse/openvsx/adapter/UpstreamVSCodeService.java b/server/src/main/java/org/eclipse/openvsx/adapter/UpstreamVSCodeService.java index 08e7a8328..2d96713f6 100644 --- a/server/src/main/java/org/eclipse/openvsx/adapter/UpstreamVSCodeService.java +++ b/server/src/main/java/org/eclipse/openvsx/adapter/UpstreamVSCodeService.java @@ -10,7 +10,7 @@ package org.eclipse.openvsx.adapter; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.UpstreamProxyService; import org.eclipse.openvsx.UrlConfigService; import org.eclipse.openvsx.util.HttpHeadersUtil; @@ -49,7 +49,7 @@ public class UpstreamVSCodeService implements IVSCodeService { UrlConfigService urlConfigService; public boolean isValid() { - return !Strings.isNullOrEmpty(urlConfigService.getUpstreamUrl()); + return !StringUtils.isEmpty(urlConfigService.getUpstreamUrl()); } @Override diff --git a/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeAPI.java b/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeAPI.java index ec697a347..1c2b1ed97 100644 --- a/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeAPI.java +++ b/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeAPI.java @@ -21,7 +21,7 @@ import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.ModelAndView; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; @RestController diff --git a/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeIdService.java b/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeIdService.java index 3cb55ad75..e69e541da 100644 --- a/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeIdService.java +++ b/server/src/main/java/org/eclipse/openvsx/adapter/VSCodeIdService.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx.adapter; -import com.google.common.base.Strings; import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.UrlConfigService; import org.eclipse.openvsx.entities.Extension; import org.eclipse.openvsx.repositories.RepositoryService; @@ -71,7 +71,7 @@ private String createRandomId() { private ExtensionQueryResult.Extension getUpstreamExtension(Extension extension) { var galleryUrl = urlConfigService.getUpstreamGalleryUrl(); - if (Strings.isNullOrEmpty(galleryUrl)) { + if (StringUtils.isEmpty(galleryUrl)) { return null; } diff --git a/server/src/main/java/org/eclipse/openvsx/admin/AdminAPI.java b/server/src/main/java/org/eclipse/openvsx/admin/AdminAPI.java index af8cc0bc5..f9c426066 100644 --- a/server/src/main/java/org/eclipse/openvsx/admin/AdminAPI.java +++ b/server/src/main/java/org/eclipse/openvsx/admin/AdminAPI.java @@ -16,8 +16,8 @@ import java.net.URI; import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.LocalRegistryService; import org.eclipse.openvsx.entities.AdminStatistics; import org.eclipse.openvsx.entities.ExtensionVersion; @@ -132,7 +132,7 @@ public String getLog(@RequestParam(name = "period", required = false) String per admins.checkAdminUser(); Streamable logs; - if (Strings.isNullOrEmpty(periodString)) { + if (StringUtils.isEmpty(periodString)) { logs = repositories.findAllPersistedLogs(); } else { try { diff --git a/server/src/main/java/org/eclipse/openvsx/admin/AdminService.java b/server/src/main/java/org/eclipse/openvsx/admin/AdminService.java index 2294e9bdb..1aaaf4a2f 100644 --- a/server/src/main/java/org/eclipse/openvsx/admin/AdminService.java +++ b/server/src/main/java/org/eclipse/openvsx/admin/AdminService.java @@ -9,7 +9,9 @@ ********************************************************************************/ package org.eclipse.openvsx.admin; -import com.google.common.base.Strings; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.ExtensionService; import org.eclipse.openvsx.ExtensionValidator; import org.eclipse.openvsx.UserService; @@ -18,7 +20,6 @@ import org.eclipse.openvsx.entities.*; import org.eclipse.openvsx.json.*; import org.eclipse.openvsx.migration.HandlerJobRequest; -import org.eclipse.openvsx.migration.MigrationRunner; import org.eclipse.openvsx.repositories.RepositoryService; import org.eclipse.openvsx.search.SearchUtilService; import org.eclipse.openvsx.storage.StorageUtilService; @@ -31,10 +32,7 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; import java.nio.charset.StandardCharsets; -import java.time.Instant; import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; @@ -213,10 +211,10 @@ public ResultJson createNamespace(NamespaceJson json) { } public void changeNamespace(ChangeNamespaceJson json) { - if (Strings.isNullOrEmpty(json.oldNamespace)) { + if (StringUtils.isEmpty(json.oldNamespace)) { throw new ErrorResultException("Old namespace must have a value"); } - if (Strings.isNullOrEmpty(json.newNamespace)) { + if (StringUtils.isEmpty(json.newNamespace)) { throw new ErrorResultException("New namespace must have a value"); } diff --git a/server/src/main/java/org/eclipse/openvsx/admin/AdminStatisticsService.java b/server/src/main/java/org/eclipse/openvsx/admin/AdminStatisticsService.java index 0db4d3b9f..cfa21c05b 100644 --- a/server/src/main/java/org/eclipse/openvsx/admin/AdminStatisticsService.java +++ b/server/src/main/java/org/eclipse/openvsx/admin/AdminStatisticsService.java @@ -13,8 +13,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.util.Map; @Component diff --git a/server/src/main/java/org/eclipse/openvsx/admin/ChangeNamespaceService.java b/server/src/main/java/org/eclipse/openvsx/admin/ChangeNamespaceService.java index 35915a05e..54dc77eee 100644 --- a/server/src/main/java/org/eclipse/openvsx/admin/ChangeNamespaceService.java +++ b/server/src/main/java/org/eclipse/openvsx/admin/ChangeNamespaceService.java @@ -19,8 +19,8 @@ import org.springframework.data.util.Streamable; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.util.List; import java.util.stream.Collectors; diff --git a/server/src/main/java/org/eclipse/openvsx/eclipse/EclipseService.java b/server/src/main/java/org/eclipse/openvsx/eclipse/EclipseService.java index 5c33d17f7..df2637b5a 100644 --- a/server/src/main/java/org/eclipse/openvsx/eclipse/EclipseService.java +++ b/server/src/main/java/org/eclipse/openvsx/eclipse/EclipseService.java @@ -21,9 +21,10 @@ import java.util.function.Function; import java.util.regex.Pattern; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.ExtensionService; import org.eclipse.openvsx.entities.AuthToken; import org.eclipse.openvsx.entities.EclipseData; @@ -56,7 +57,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Strings; import com.google.common.collect.Lists; @Component @@ -108,7 +108,7 @@ public EclipseService() { private final Function parseDate = dateString -> { try { var local = LocalDateTime.parse(dateString, CUSTOM_DATE_TIME); - if (Strings.isNullOrEmpty(publisherAgreementTimeZone)) { + if (StringUtils.isEmpty(publisherAgreementTimeZone)) { return local; } return TimeUtil.convertToUTC(local, publisherAgreementTimeZone); @@ -119,7 +119,7 @@ public EclipseService() { }; public boolean isActive() { - return !Strings.isNullOrEmpty(publisherAgreementVersion); + return !StringUtils.isEmpty(publisherAgreementVersion); } /** @@ -164,7 +164,7 @@ public EclipseData updateUserData(UserData user, EclipseProfile profile) { eclipseData = user.getEclipseData().clone(); } - if (Strings.isNullOrEmpty(eclipseData.personId)) { + if (StringUtils.isEmpty(eclipseData.personId)) { eclipseData.personId = profile.name; } if (profile.publisherAgreements != null) { @@ -172,7 +172,7 @@ public EclipseData updateUserData(UserData user, EclipseProfile profile) { if (eclipseData.publisherAgreement != null) { eclipseData.publisherAgreement.isActive = false; } - } else if (!Strings.isNullOrEmpty(profile.publisherAgreements.openVsx.version)) { + } else if (!StringUtils.isEmpty(profile.publisherAgreements.openVsx.version)) { if (eclipseData.publisherAgreement == null) { eclipseData.publisherAgreement = new EclipseData.PublisherAgreement(); } @@ -321,7 +321,7 @@ public EclipseData.PublisherAgreement getPublisherAgreement(UserData user) { */ public EclipseData.PublisherAgreement getPublisherAgreement(UserData user, String accessToken) { var eclipseData = user.getEclipseData(); - if (eclipseData == null || Strings.isNullOrEmpty(eclipseData.personId)) { + if (eclipseData == null || StringUtils.isEmpty(eclipseData.personId)) { return null; } checkApiUrl(); @@ -482,14 +482,14 @@ public void revokePublisherAgreement(UserData user, UserData admin) { } private void checkApiUrl() { - if (Strings.isNullOrEmpty(eclipseApiUrl)) { + if (StringUtils.isEmpty(eclipseApiUrl)) { throw new ErrorResultException("Missing URL for Eclipse API."); } } private AuthToken checkEclipseToken(UserData user) { var eclipseToken = tokens.getActiveToken(user, "eclipse"); - if (eclipseToken == null || Strings.isNullOrEmpty(eclipseToken.accessToken)) { + if (eclipseToken == null || StringUtils.isEmpty(eclipseToken.accessToken)) { throw new ErrorResultException("Authorization by Eclipse required.", HttpStatus.FORBIDDEN); } return eclipseToken; @@ -497,7 +497,7 @@ private AuthToken checkEclipseToken(UserData user) { private EclipseData checkEclipseData(UserData user) { var eclipseData = user.getEclipseData(); - if (eclipseData == null || Strings.isNullOrEmpty(eclipseData.personId)) { + if (eclipseData == null || StringUtils.isEmpty(eclipseData.personId)) { throw new ErrorResultException("Eclipse person ID is unavailable for user: " + user.getProvider() + "/" + user.getLoginName()); } diff --git a/server/src/main/java/org/eclipse/openvsx/eclipse/PublisherComplianceChecker.java b/server/src/main/java/org/eclipse/openvsx/eclipse/PublisherComplianceChecker.java index a1fc8f38b..76dea5fa7 100644 --- a/server/src/main/java/org/eclipse/openvsx/eclipse/PublisherComplianceChecker.java +++ b/server/src/main/java/org/eclipse/openvsx/eclipse/PublisherComplianceChecker.java @@ -11,7 +11,7 @@ import java.util.LinkedHashSet; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import org.eclipse.openvsx.ExtensionService; import org.eclipse.openvsx.entities.Extension; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/AdminStatistics.java b/server/src/main/java/org/eclipse/openvsx/entities/AdminStatistics.java index 54f37af98..31ac57de5 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/AdminStatistics.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/AdminStatistics.java @@ -11,7 +11,7 @@ import org.eclipse.openvsx.json.AdminStatisticsJson; -import javax.persistence.*; +import jakarta.persistence.*; import java.util.ArrayList; import java.util.Comparator; import java.util.List; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/AuthTokenConverter.java b/server/src/main/java/org/eclipse/openvsx/entities/AuthTokenConverter.java index 8211f3411..ad20b3075 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/AuthTokenConverter.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/AuthTokenConverter.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/AzureDownloadCountProcessedItem.java b/server/src/main/java/org/eclipse/openvsx/entities/AzureDownloadCountProcessedItem.java index f9a0794c6..da0403309 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/AzureDownloadCountProcessedItem.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/AzureDownloadCountProcessedItem.java @@ -9,7 +9,7 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.LocalDateTime; @Entity diff --git a/server/src/main/java/org/eclipse/openvsx/entities/Download.java b/server/src/main/java/org/eclipse/openvsx/entities/Download.java index 615cb62a3..0847e1279 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/Download.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/Download.java @@ -9,7 +9,7 @@ * ****************************************************************************** */ package org.eclipse.openvsx.entities; -import javax.persistence.*; +import jakarta.persistence.*; import java.time.LocalDateTime; @Entity diff --git a/server/src/main/java/org/eclipse/openvsx/entities/EclipseDataConverter.java b/server/src/main/java/org/eclipse/openvsx/entities/EclipseDataConverter.java index 2bf5203d3..f011dab4b 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/EclipseDataConverter.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/EclipseDataConverter.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/Extension.java b/server/src/main/java/org/eclipse/openvsx/entities/Extension.java index 5e4c01054..5aaa1593c 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/Extension.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/Extension.java @@ -15,7 +15,7 @@ import java.util.*; import java.util.stream.Collectors; -import javax.persistence.*; +import jakarta.persistence.*; import org.eclipse.openvsx.search.ExtensionSearch; import org.eclipse.openvsx.util.NamingUtil; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/ExtensionReview.java b/server/src/main/java/org/eclipse/openvsx/entities/ExtensionReview.java index 6763c7a8b..171e7d6fa 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/ExtensionReview.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/ExtensionReview.java @@ -11,11 +11,11 @@ import java.time.LocalDateTime; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; import org.eclipse.openvsx.json.ReviewJson; import org.eclipse.openvsx.util.TimeUtil; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/ExtensionVersion.java b/server/src/main/java/org/eclipse/openvsx/entities/ExtensionVersion.java index f06158d0b..33d625c1b 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/ExtensionVersion.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/ExtensionVersion.java @@ -14,7 +14,7 @@ import java.util.*; import java.util.stream.Collectors; -import javax.persistence.*; +import jakarta.persistence.*; import org.apache.jena.ext.com.google.common.collect.Maps; import org.eclipse.openvsx.json.ExtensionJson; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/FileResource.java b/server/src/main/java/org/eclipse/openvsx/entities/FileResource.java index fa7712e5c..19f7ca87d 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/FileResource.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/FileResource.java @@ -9,7 +9,7 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; -import javax.persistence.*; +import jakarta.persistence.*; @Entity public class FileResource { diff --git a/server/src/main/java/org/eclipse/openvsx/entities/ListOfStringConverter.java b/server/src/main/java/org/eclipse/openvsx/entities/ListOfStringConverter.java index f7961e4a8..2bbce2cbc 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/ListOfStringConverter.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/ListOfStringConverter.java @@ -13,8 +13,8 @@ import com.google.common.base.Splitter; import com.google.common.collect.Lists; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; import java.util.List; @Converter diff --git a/server/src/main/java/org/eclipse/openvsx/entities/MigrationItem.java b/server/src/main/java/org/eclipse/openvsx/entities/MigrationItem.java index 44588d604..61270a416 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/MigrationItem.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/MigrationItem.java @@ -9,9 +9,9 @@ * ****************************************************************************** */ package org.eclipse.openvsx.entities; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; @Entity public class MigrationItem { diff --git a/server/src/main/java/org/eclipse/openvsx/entities/Namespace.java b/server/src/main/java/org/eclipse/openvsx/entities/Namespace.java index e5c393d98..159e4e1f4 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/Namespace.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/Namespace.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.json.NamespaceDetailsJson; -import org.elasticsearch.common.Strings; import java.io.Serializable; import java.util.Arrays; @@ -19,7 +19,7 @@ import java.util.Objects; import java.util.stream.Collectors; -import javax.persistence.*; +import jakarta.persistence.*; @Entity @Table(uniqueConstraints = { @@ -155,7 +155,7 @@ public Map getSocialLinks() { public void setSocialLinks(Map socialLinks) { this.socialLinks = socialLinks.entrySet().stream() - .filter(e -> !Strings.isNullOrEmpty(e.getValue())) + .filter(e -> !StringUtils.isEmpty(e.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } diff --git a/server/src/main/java/org/eclipse/openvsx/entities/NamespaceMembership.java b/server/src/main/java/org/eclipse/openvsx/entities/NamespaceMembership.java index bac52d653..70e88594f 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/NamespaceMembership.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/NamespaceMembership.java @@ -9,12 +9,12 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import org.eclipse.openvsx.json.NamespaceMembershipJson; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/PersistedLog.java b/server/src/main/java/org/eclipse/openvsx/entities/PersistedLog.java index 35123d71d..9f2d09f94 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/PersistedLog.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/PersistedLog.java @@ -11,13 +11,13 @@ import java.time.LocalDateTime; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.ForeignKey; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.ForeignKey; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; @Entity public class PersistedLog { diff --git a/server/src/main/java/org/eclipse/openvsx/entities/PersonalAccessToken.java b/server/src/main/java/org/eclipse/openvsx/entities/PersonalAccessToken.java index 8e42364a0..53db1915a 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/PersonalAccessToken.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/PersonalAccessToken.java @@ -14,15 +14,15 @@ import java.util.List; import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import javax.persistence.UniqueConstraint; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import org.eclipse.openvsx.json.AccessTokenJson; import org.eclipse.openvsx.util.TimeUtil; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/SemanticVersion.java b/server/src/main/java/org/eclipse/openvsx/entities/SemanticVersion.java index d41a03e49..d73742d52 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/SemanticVersion.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/SemanticVersion.java @@ -9,9 +9,9 @@ ********************************************************************************/ package org.eclipse.openvsx.entities; -import org.jooq.tools.StringUtils; +import org.apache.commons.lang3.StringUtils; -import javax.persistence.Embeddable; +import jakarta.persistence.Embeddable; import java.io.Serializable; import java.util.List; import java.util.Objects; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/SignatureKeyPair.java b/server/src/main/java/org/eclipse/openvsx/entities/SignatureKeyPair.java index ae7a8f1dc..32372254b 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/SignatureKeyPair.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/SignatureKeyPair.java @@ -9,10 +9,10 @@ * ****************************************************************************** */ package org.eclipse.openvsx.entities; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; import java.io.Serializable; import java.time.LocalDateTime; import java.util.Arrays; diff --git a/server/src/main/java/org/eclipse/openvsx/entities/UserData.java b/server/src/main/java/org/eclipse/openvsx/entities/UserData.java index 7f2ae9ea6..fa821f814 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/UserData.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/UserData.java @@ -13,12 +13,12 @@ import java.util.List; import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToMany; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import org.eclipse.openvsx.json.UserJson; diff --git a/server/src/main/java/org/eclipse/openvsx/json/ExtensionJson.java b/server/src/main/java/org/eclipse/openvsx/json/ExtensionJson.java index 95be9873e..5b8596382 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/ExtensionJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/ExtensionJson.java @@ -14,9 +14,9 @@ import java.util.Map; import java.util.Objects; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/ExtensionReferenceJson.java b/server/src/main/java/org/eclipse/openvsx/json/ExtensionReferenceJson.java index b988f57b9..3ed8f915b 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/ExtensionReferenceJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/ExtensionReferenceJson.java @@ -9,7 +9,7 @@ ********************************************************************************/ package org.eclipse.openvsx.json; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/NamespaceDetailsJson.java b/server/src/main/java/org/eclipse/openvsx/json/NamespaceDetailsJson.java index 99d4927bf..701224a70 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/NamespaceDetailsJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/NamespaceDetailsJson.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import java.io.Serializable; import java.util.Arrays; import java.util.List; diff --git a/server/src/main/java/org/eclipse/openvsx/json/NamespaceJson.java b/server/src/main/java/org/eclipse/openvsx/json/NamespaceJson.java index 42c26c508..7bf14bc00 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/NamespaceJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/NamespaceJson.java @@ -11,7 +11,7 @@ import java.util.Map; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/NamespaceMembershipListJson.java b/server/src/main/java/org/eclipse/openvsx/json/NamespaceMembershipListJson.java index a1854ad69..285678d7c 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/NamespaceMembershipListJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/NamespaceMembershipListJson.java @@ -11,7 +11,7 @@ import java.util.List; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/QueryParamJson.java b/server/src/main/java/org/eclipse/openvsx/json/QueryParamJson.java index 56dfebf58..95bfc22f1 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/QueryParamJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/QueryParamJson.java @@ -11,8 +11,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.google.common.base.Strings; import io.swagger.v3.oas.annotations.media.Schema; +import org.apache.commons.lang3.StringUtils; import java.util.LinkedHashMap; import java.util.stream.Stream; @@ -80,7 +80,7 @@ public String[] toQueryParams() { } return queryParams.entrySet().stream() - .filter(entry -> !Strings.isNullOrEmpty(entry.getValue())) + .filter(entry -> !StringUtils.isEmpty(entry.getValue())) .flatMap(entry -> Stream.of(entry.getKey(), entry.getValue())) .toArray(String[]::new); } diff --git a/server/src/main/java/org/eclipse/openvsx/json/QueryResultJson.java b/server/src/main/java/org/eclipse/openvsx/json/QueryResultJson.java index 79cf833ee..8577317fd 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/QueryResultJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/QueryResultJson.java @@ -16,8 +16,8 @@ import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; @Schema( name = "QueryResult", diff --git a/server/src/main/java/org/eclipse/openvsx/json/ReviewJson.java b/server/src/main/java/org/eclipse/openvsx/json/ReviewJson.java index 59e1205fc..25470e8e2 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/ReviewJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/ReviewJson.java @@ -9,9 +9,9 @@ ********************************************************************************/ package org.eclipse.openvsx.json; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/ReviewListJson.java b/server/src/main/java/org/eclipse/openvsx/json/ReviewListJson.java index 12b9df2a4..9b700a508 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/ReviewListJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/ReviewListJson.java @@ -11,7 +11,7 @@ import java.util.List; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/SearchEntryJson.java b/server/src/main/java/org/eclipse/openvsx/json/SearchEntryJson.java index 63ded3b03..12b7b13bf 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/SearchEntryJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/SearchEntryJson.java @@ -13,9 +13,9 @@ import java.util.List; import java.util.Map; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/SearchResultJson.java b/server/src/main/java/org/eclipse/openvsx/json/SearchResultJson.java index b7a542124..e9d37a8b5 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/SearchResultJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/SearchResultJson.java @@ -11,8 +11,8 @@ import java.util.List; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/TargetPlatformVersionJson.java b/server/src/main/java/org/eclipse/openvsx/json/TargetPlatformVersionJson.java index 6c8d69ca1..634444f19 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/TargetPlatformVersionJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/TargetPlatformVersionJson.java @@ -9,7 +9,7 @@ * ****************************************************************************** */ package org.eclipse.openvsx.json; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; public class TargetPlatformVersionJson { /*** diff --git a/server/src/main/java/org/eclipse/openvsx/json/UserJson.java b/server/src/main/java/org/eclipse/openvsx/json/UserJson.java index 38398e6c1..a4e9641e9 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/UserJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/UserJson.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Objects; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/UserPublishInfoJson.java b/server/src/main/java/org/eclipse/openvsx/json/UserPublishInfoJson.java index b56e5fb28..f9577baa8 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/UserPublishInfoJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/UserPublishInfoJson.java @@ -11,7 +11,7 @@ import java.util.List; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/server/src/main/java/org/eclipse/openvsx/json/VersionReferencesJson.java b/server/src/main/java/org/eclipse/openvsx/json/VersionReferencesJson.java index bdbe6cd8f..d129f100d 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/VersionReferencesJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/VersionReferencesJson.java @@ -12,8 +12,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import java.util.List; @Schema( diff --git a/server/src/main/java/org/eclipse/openvsx/json/VersionsJson.java b/server/src/main/java/org/eclipse/openvsx/json/VersionsJson.java index 1219fa5d2..8a48238ac 100644 --- a/server/src/main/java/org/eclipse/openvsx/json/VersionsJson.java +++ b/server/src/main/java/org/eclipse/openvsx/json/VersionsJson.java @@ -12,8 +12,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import java.util.Map; @Schema( diff --git a/server/src/main/java/org/eclipse/openvsx/migration/ExtractResourcesJobService.java b/server/src/main/java/org/eclipse/openvsx/migration/ExtractResourcesJobService.java index 7ce1de73f..38f6d381d 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/ExtractResourcesJobService.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/ExtractResourcesJobService.java @@ -14,7 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.transaction.Transactional; +import jakarta.transaction.Transactional; @Component public class ExtractResourcesJobService { diff --git a/server/src/main/java/org/eclipse/openvsx/migration/FixTargetPlatformsService.java b/server/src/main/java/org/eclipse/openvsx/migration/FixTargetPlatformsService.java index e8fe00547..6e87a38d5 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/FixTargetPlatformsService.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/FixTargetPlatformsService.java @@ -14,8 +14,8 @@ import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; @Component public class FixTargetPlatformsService { diff --git a/server/src/main/java/org/eclipse/openvsx/migration/GenerateKeyPairJobService.java b/server/src/main/java/org/eclipse/openvsx/migration/GenerateKeyPairJobService.java index 32c072c37..9a06c1a42 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/GenerateKeyPairJobService.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/GenerateKeyPairJobService.java @@ -21,8 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; diff --git a/server/src/main/java/org/eclipse/openvsx/migration/MigrationService.java b/server/src/main/java/org/eclipse/openvsx/migration/MigrationService.java index 6f77a686d..7f6759731 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/MigrationService.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/MigrationService.java @@ -25,8 +25,8 @@ import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; diff --git a/server/src/main/java/org/eclipse/openvsx/migration/OrphanNamespaceMigration.java b/server/src/main/java/org/eclipse/openvsx/migration/OrphanNamespaceMigration.java index 50492357e..d09fff2ab 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/OrphanNamespaceMigration.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/OrphanNamespaceMigration.java @@ -17,8 +17,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.util.LinkedHashSet; @Component diff --git a/server/src/main/java/org/eclipse/openvsx/migration/RenameDownloadsService.java b/server/src/main/java/org/eclipse/openvsx/migration/RenameDownloadsService.java index 229d6bf66..4af773e06 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/RenameDownloadsService.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/RenameDownloadsService.java @@ -15,8 +15,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; @Component public class RenameDownloadsService { diff --git a/server/src/main/java/org/eclipse/openvsx/migration/SetPreReleaseJobService.java b/server/src/main/java/org/eclipse/openvsx/migration/SetPreReleaseJobService.java index 0a7d5bd47..1b08bc2b3 100644 --- a/server/src/main/java/org/eclipse/openvsx/migration/SetPreReleaseJobService.java +++ b/server/src/main/java/org/eclipse/openvsx/migration/SetPreReleaseJobService.java @@ -18,8 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.util.List; @Component diff --git a/server/src/main/java/org/eclipse/openvsx/mirror/DataMirrorService.java b/server/src/main/java/org/eclipse/openvsx/mirror/DataMirrorService.java index c7511525d..f46b4dee8 100644 --- a/server/src/main/java/org/eclipse/openvsx/mirror/DataMirrorService.java +++ b/server/src/main/java/org/eclipse/openvsx/mirror/DataMirrorService.java @@ -16,8 +16,8 @@ import java.util.Set; import java.util.stream.Collectors; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import org.eclipse.openvsx.*; import org.eclipse.openvsx.admin.AdminService; diff --git a/server/src/main/java/org/eclipse/openvsx/mirror/MirrorExtensionHandlerInterceptor.java b/server/src/main/java/org/eclipse/openvsx/mirror/MirrorExtensionHandlerInterceptor.java index 596b7d6eb..f217da06f 100644 --- a/server/src/main/java/org/eclipse/openvsx/mirror/MirrorExtensionHandlerInterceptor.java +++ b/server/src/main/java/org/eclipse/openvsx/mirror/MirrorExtensionHandlerInterceptor.java @@ -15,8 +15,8 @@ import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerMapping; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Collections; import java.util.Map; import java.util.TreeMap; diff --git a/server/src/main/java/org/eclipse/openvsx/mirror/ReadOnlyRequestFilter.java b/server/src/main/java/org/eclipse/openvsx/mirror/ReadOnlyRequestFilter.java index b94563ee4..ee2694805 100644 --- a/server/src/main/java/org/eclipse/openvsx/mirror/ReadOnlyRequestFilter.java +++ b/server/src/main/java/org/eclipse/openvsx/mirror/ReadOnlyRequestFilter.java @@ -12,9 +12,9 @@ import java.util.Arrays; import java.util.List; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; import org.springframework.web.filter.OncePerRequestFilter; diff --git a/server/src/main/java/org/eclipse/openvsx/publish/ExtensionVersionIntegrityService.java b/server/src/main/java/org/eclipse/openvsx/publish/ExtensionVersionIntegrityService.java index 5494c94d6..7d989d921 100644 --- a/server/src/main/java/org/eclipse/openvsx/publish/ExtensionVersionIntegrityService.java +++ b/server/src/main/java/org/eclipse/openvsx/publish/ExtensionVersionIntegrityService.java @@ -30,8 +30,8 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Files; diff --git a/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionHandler.java b/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionHandler.java index c851140c2..6ebcd6989 100644 --- a/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionHandler.java +++ b/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionHandler.java @@ -27,8 +27,8 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.IOException; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionService.java b/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionService.java index bd6c42638..464cf8674 100644 --- a/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionService.java +++ b/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionService.java @@ -21,8 +21,8 @@ import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.IOException; import java.nio.file.Files; diff --git a/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java b/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java index e13e7be12..6b5da56f8 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java @@ -9,9 +9,10 @@ * ****************************************************************************** */ package org.eclipse.openvsx.repositories; -import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.*; import org.eclipse.openvsx.json.QueryRequest; +import org.jooq.Record; import org.jooq.*; import org.jooq.impl.DSL; import org.springframework.beans.factory.annotation.Autowired; @@ -268,22 +269,22 @@ private List findVersionStringsSorted(List conditions, Pageab public Page findActiveVersions(QueryRequest request) { var conditions = new ArrayList(); - if (!Strings.isNullOrEmpty(request.namespaceUuid)) { + if (!StringUtils.isEmpty(request.namespaceUuid)) { conditions.add(NAMESPACE.PUBLIC_ID.eq(request.namespaceUuid)); } - if (!Strings.isNullOrEmpty(request.namespaceName)) { + if (!StringUtils.isEmpty(request.namespaceName)) { conditions.add(NAMESPACE.NAME.eq(request.namespaceName)); } - if (!Strings.isNullOrEmpty(request.extensionUuid)) { + if (!StringUtils.isEmpty(request.extensionUuid)) { conditions.add(EXTENSION.PUBLIC_ID.eq(request.extensionUuid)); } - if (!Strings.isNullOrEmpty(request.extensionName)) { + if (!StringUtils.isEmpty(request.extensionName)) { conditions.add(EXTENSION.NAME.eq(request.extensionName)); } if(request.targetPlatform != null) { conditions.add(EXTENSION_VERSION.TARGET_PLATFORM.eq(request.targetPlatform)); } - if (!Strings.isNullOrEmpty(request.extensionVersion)) { + if (!StringUtils.isEmpty(request.extensionVersion)) { conditions.add(EXTENSION_VERSION.VERSION.eq(request.extensionVersion)); } diff --git a/server/src/main/java/org/eclipse/openvsx/repositories/FileResourceJooqRepository.java b/server/src/main/java/org/eclipse/openvsx/repositories/FileResourceJooqRepository.java index b30f5e3ea..cd9745c84 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/FileResourceJooqRepository.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/FileResourceJooqRepository.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Component; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -30,6 +31,10 @@ public class FileResourceJooqRepository { DSLContext dsl; public List findByType(Collection extVersions, Collection types) { + if(extVersions.isEmpty() || types.isEmpty()) { + return Collections.emptyList(); + } + var extVersionsById = extVersions.stream().collect(Collectors.toMap(ExtensionVersion::getId, ev -> ev)); return dsl.select(FILE_RESOURCE.ID, FILE_RESOURCE.EXTENSION_ID, FILE_RESOURCE.NAME, FILE_RESOURCE.TYPE) .from(FILE_RESOURCE) diff --git a/server/src/main/java/org/eclipse/openvsx/repositories/NamespaceMembershipJooqRepository.java b/server/src/main/java/org/eclipse/openvsx/repositories/NamespaceMembershipJooqRepository.java index f05de1c0b..7b251c542 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/NamespaceMembershipJooqRepository.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/NamespaceMembershipJooqRepository.java @@ -56,4 +56,18 @@ private NamespaceMembership toNamespaceMembership(Record record) { return namespaceMembership; } + + public boolean isVerified(Namespace namespace, UserData user) { + var nm = NAMESPACE_MEMBERSHIP.as("nm"); + var onm = NAMESPACE_MEMBERSHIP.as("onm"); + var result = dsl.selectOne() + .from(nm) + .join(onm).on(onm.NAMESPACE.eq(nm.NAMESPACE)) + .where(onm.NAMESPACE.eq(namespace.getId())) + .and(onm.ROLE.eq(NamespaceMembership.ROLE_OWNER)) + .and(nm.USER_DATA.eq(user.getId())) + .fetch(); + + return result.isNotEmpty(); + } } diff --git a/server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java b/server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java index a89ac8beb..cab73ff37 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java @@ -50,7 +50,7 @@ public class RepositoryService { @Autowired ExtensionJooqRepository extensionJooqRepo; @Autowired ExtensionVersionJooqRepository extensionVersionJooqRepo; @Autowired FileResourceJooqRepository fileResourceJooqRepo; - @Autowired NamespaceMembershipJooqRepository namespaceMembershipJooqRepo; + @Autowired NamespaceMembershipJooqRepository membershipJooqRepo; @Autowired AdminStatisticsRepository adminStatisticsRepo; @Autowired AdminStatisticCalculationsRepository adminStatisticCalculationsRepo; @Autowired MigrationItemRepository migrationItemRepo; @@ -265,8 +265,8 @@ public NamespaceMembership findMembership(UserData user, Namespace namespace) { return membershipRepo.findByUserAndNamespace(user, namespace); } - public long countMemberships(UserData user, Namespace namespace) { - return membershipRepo.countByUserAndNamespace(user, namespace); + public boolean isVerified(Namespace namespace, UserData user) { + return membershipJooqRepo.isVerified(namespace, user); } public Streamable findMemberships(Namespace namespace, String role) { @@ -358,7 +358,7 @@ public List findResourceFileResources(long extVersionId, String pr } public List findNamespaceMemberships(Collection namespaceIds) { - return namespaceMembershipJooqRepo.findAllByNamespaceId(namespaceIds); + return membershipJooqRepo.findAllByNamespaceId(namespaceIds); } public AdminStatistics findAdminStatisticsByYearAndMonth(int year, int month) { diff --git a/server/src/main/java/org/eclipse/openvsx/search/DatabaseSearchService.java b/server/src/main/java/org/eclipse/openvsx/search/DatabaseSearchService.java index 704d87e75..192e18670 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/DatabaseSearchService.java +++ b/server/src/main/java/org/eclipse/openvsx/search/DatabaseSearchService.java @@ -27,7 +27,7 @@ import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; -import javax.transaction.Transactional; +import jakarta.transaction.Transactional; import static org.eclipse.openvsx.cache.CacheService.CACHE_AVERAGE_REVIEW_RATING; import static org.eclipse.openvsx.cache.CacheService.CACHE_DATABASE_SEARCH; @@ -63,7 +63,7 @@ public SearchHits search(ISearchService.Options options) { // no extensions in the database if (matchingExtensions.isEmpty()) { - return new SearchHitsImpl<>(0,TotalHitsRelation.OFF, 0f, "", Collections.emptyList(), null, null); + return new SearchHitsImpl<>(0,TotalHitsRelation.OFF, 0f, null, null, Collections.emptyList(), null, null); } // exlude namespaces @@ -148,7 +148,7 @@ public SearchHits search(ISearchService.Options options) { searchHits = sortedExtensions.stream().map(extensionSearch -> new SearchHit<>(null, null, null, 0.0f, null, null, null, null, null, null, extensionSearch)).collect(Collectors.toList()); } - return new SearchHitsImpl<>(totalHits, TotalHitsRelation.OFF, 0f, "", searchHits, null, null); + return new SearchHitsImpl<>(totalHits, TotalHitsRelation.OFF, 0f, null, null, searchHits, null, null); } /** @@ -180,6 +180,12 @@ public void updateSearchEntry(Extension extension) { } + @Override + @CacheEvict(value = CACHE_DATABASE_SEARCH, allEntries = true) + public void removeSearchEntries(Collection ids) { + + } + @Override @CacheEvict(value = CACHE_DATABASE_SEARCH, allEntries = true) public void removeSearchEntry(Extension extension) { diff --git a/server/src/main/java/org/eclipse/openvsx/search/ElasticSearchService.java b/server/src/main/java/org/eclipse/openvsx/search/ElasticSearchService.java index 02c5df725..cf916671a 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/ElasticSearchService.java +++ b/server/src/main/java/org/eclipse/openvsx/search/ElasticSearchService.java @@ -9,28 +9,18 @@ ********************************************************************************/ package org.eclipse.openvsx.search; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.stream.Collectors; - -import com.google.common.base.Strings; - +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.mapping.FieldType; +import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; +import co.elastic.clients.util.ObjectBuilder; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.Extension; import org.eclipse.openvsx.migration.HandlerJobRequest; import org.eclipse.openvsx.repositories.RepositoryService; import org.eclipse.openvsx.search.RelevanceService.SearchStats; import org.eclipse.openvsx.util.ErrorResultException; import org.eclipse.openvsx.util.TargetPlatform; -import org.elasticsearch.common.unit.Fuzziness; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.search.sort.SortBuilder; -import org.elasticsearch.search.sort.SortBuilders; -import org.elasticsearch.search.sort.SortOrder; import org.jobrunr.scheduling.JobRequestScheduler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,15 +32,20 @@ import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder; import org.springframework.data.elasticsearch.core.*; import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.retry.annotation.Retryable; import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; +import java.time.ZoneId; +import java.util.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; + import static org.eclipse.openvsx.cache.CacheService.CACHE_AVERAGE_REVIEW_RATING; @Component @@ -228,6 +223,18 @@ public void updateSearchEntry(Extension extension) { } } + @Retryable(DataAccessResourceFailureException.class) + public void removeSearchEntries(Collection ids) { + if (!isEnabled()) { + return; + } + + var queryBuilder = new NativeQueryBuilder(); + var query = queryBuilder.withQuery(builder -> builder.ids(idsBuilder -> idsBuilder.values(ids.stream().map(String::valueOf).collect(Collectors.toList())))).build(); + searchOperations.delete(query, ExtensionSearch.class); + } + + @Retryable(DataAccessResourceFailureException.class) public void removeSearchEntry(Extension extension) { if (!isEnabled()) { @@ -245,49 +252,12 @@ public void removeSearchEntry(Extension extension) { public SearchHits search(Options options) { var resultWindow = options.requestedOffset + options.requestedSize; if(resultWindow > getMaxResultWindow()) { - return new SearchHitsImpl<>(0, TotalHitsRelation.OFF, 0f, "", Collections.emptyList(), null, null); + return new SearchHitsImpl<>(0, TotalHitsRelation.OFF, 0f, null, null, Collections.emptyList(), null, null); } - var queryBuilder = new NativeSearchQueryBuilder(); - var boolQuery = QueryBuilders.boolQuery(); - if (!Strings.isNullOrEmpty(options.queryString)) { - boolQuery.should(QueryBuilders.termQuery("extensionId.keyword", options.queryString).caseInsensitive(true)).boost(10); - - // Fuzzy matching of search query in multiple fields - var multiMatchQuery = QueryBuilders.multiMatchQuery(options.queryString) - .field("name").boost(5) - .field("displayName").boost(5) - .field("tags").boost(3) - .field("namespace").boost(2) - .field("description") - .fuzziness(Fuzziness.AUTO) - .prefixLength(2); - boolQuery.should(multiMatchQuery).boost(5); - - // Prefix matching of search query in display name and namespace - var prefixString = options.queryString.trim().toLowerCase(); - var namePrefixQuery = QueryBuilders.prefixQuery("displayName", prefixString); - boolQuery.should(namePrefixQuery).boost(2); - var namespacePrefixQuery = QueryBuilders.prefixQuery("namespace", prefixString); - boolQuery.should(namespacePrefixQuery); - } + var queryBuilder = new NativeQueryBuilder(); + queryBuilder.withQuery(builder -> builder.bool(boolQuery -> createSearchQuery(boolQuery, options))); - if (!Strings.isNullOrEmpty(options.category)) { - // Filter by selected category - boolQuery.must(QueryBuilders.matchPhraseQuery("categories", options.category)); - } - if (TargetPlatform.isValid(options.targetPlatform)) { - // Filter by selected target platform - boolQuery.must(QueryBuilders.matchPhraseQuery("targetPlatforms", options.targetPlatform)); - } - if (options.namespacesToExclude != null) { - // Exclude namespaces - for(var namespaceToExclude : options.namespacesToExclude) { - boolQuery.mustNot(QueryBuilders.termQuery("namespace.keyword", namespaceToExclude)); - } - } - - queryBuilder.withQuery(boolQuery); // Sort search results according to 'sortOrder' and 'sortBy' options sortResults(queryBuilder, options.sortOrder, options.sortBy); @@ -325,6 +295,7 @@ public SearchHits search(Options options) { firstSearchHitsPage.getTotalHitsRelation(), firstSearchHitsPage.getMaxScore(), null, + null, searchHits, null, null @@ -334,16 +305,68 @@ public SearchHits search(Options options) { } } - private void sortResults(NativeSearchQueryBuilder queryBuilder, String sortOrder, String sortBy) { - if (!"asc".equalsIgnoreCase(sortOrder) && !"desc".equalsIgnoreCase(sortOrder)) { + private ObjectBuilder createSearchQuery(BoolQuery.Builder boolQuery, Options options) { + if (!StringUtils.isEmpty(options.queryString)) { + boolQuery.should(QueryBuilders.term(builder -> + builder.field("extensionId.keyword") + .value(options.queryString) + .caseInsensitive(true) + .boost(10f) + )); + + // Fuzzy matching of search query in multiple fields + var multiMatchQuery = QueryBuilders.multiMatch(builder -> + builder.query(options.queryString) + .fields("name").boost(5f) + .fields("displayName").boost(5f) + .fields("tags").boost(3f) + .fields("namespace").boost(2f) + .fields("description") + .fuzziness("AUTO") + .prefixLength(2) + ); + + boolQuery.should(multiMatchQuery).boost(5f); + + // Prefix matching of search query in display name and namespace + var prefixString = options.queryString.trim().toLowerCase(); + var namePrefixQuery = QueryBuilders.prefix(builder -> builder.field("displayName").value(prefixString)); + boolQuery.should(namePrefixQuery).boost(2f); + var namespacePrefixQuery = QueryBuilders.prefix(builder -> builder.field("namespace").value(prefixString)); + boolQuery.should(namespacePrefixQuery); + } + + if (!StringUtils.isEmpty(options.category)) { + // Filter by selected category + boolQuery.must(QueryBuilders.matchPhrase(builder -> builder.field("categories").query(options.category))); + } + if (TargetPlatform.isValid(options.targetPlatform)) { + // Filter by selected target platform + boolQuery.must(QueryBuilders.matchPhrase(builder -> builder.field("targetPlatforms").query(options.targetPlatform))); + } + if (options.namespacesToExclude != null) { + // Exclude namespaces + for(var namespaceToExclude : options.namespacesToExclude) { + boolQuery.mustNot(QueryBuilders.term(builder -> builder.field("namespace.keyword").value(namespaceToExclude))); + } + } + + return boolQuery; + } + + private void sortResults(NativeQueryBuilder queryBuilder, String sortOrder, String sortBy) { + sortOrder = sortOrder.toLowerCase(); + var orders = Map.of("asc", SortOrder.Asc, "desc", SortOrder.Desc); + var order = orders.get(sortOrder); + if (order == null) { throw new ErrorResultException("sortOrder parameter must be either 'asc' or 'desc'."); } var types = Map.of( - "relevance", "float", - "rating", "float", - "timestamp", "long", - "downloadCount", "integer" + "relevance", FieldType.Float, + "rating", FieldType.Float, + "timestamp", FieldType.Long, + "downloadCount", FieldType.Integer ); var type = types.get(sortBy); @@ -351,14 +374,10 @@ private void sortResults(NativeSearchQueryBuilder queryBuilder, String sortOrder throw new ErrorResultException("sortBy parameter must be 'relevance', 'timestamp', 'averageRating' or 'downloadCount'."); } if ("relevance".equals(sortBy)) { - queryBuilder.withSorts(SortBuilders.scoreSort(), fieldSort(sortBy, type, sortOrder)); - } else { - queryBuilder.withSorts(fieldSort(sortBy, type, sortOrder)); + queryBuilder.withSort(builder -> builder.score(scoreSort -> scoreSort.order(order))); } - } - private SortBuilder fieldSort(String sortBy, String type, String sortOrder) { - return SortBuilders.fieldSort(sortBy).unmappedType(type).order(SortOrder.fromString(sortOrder)); + queryBuilder.withSort(builder -> builder.field(fieldSort -> fieldSort.field(sortBy).unmappedType(type).order(order))); } private long getMaxResultWindow() { diff --git a/server/src/main/java/org/eclipse/openvsx/search/ISearchService.java b/server/src/main/java/org/eclipse/openvsx/search/ISearchService.java index 1e1185565..9f6d1e6ae 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/ISearchService.java +++ b/server/src/main/java/org/eclipse/openvsx/search/ISearchService.java @@ -10,6 +10,7 @@ package org.eclipse.openvsx.search; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Objects; import org.springframework.data.elasticsearch.core.SearchHits; @@ -56,6 +57,11 @@ public interface ISearchService { */ void removeSearchEntry(Extension extension); + /** + * The given extensions have been removed from the registry, we need to refresh the search index. + */ + void removeSearchEntries(Collection ids); + public static class Options { public final String queryString; public final String category; diff --git a/server/src/main/java/org/eclipse/openvsx/search/RelevanceService.java b/server/src/main/java/org/eclipse/openvsx/search/RelevanceService.java index f9203e7c9..4b20c5120 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/RelevanceService.java +++ b/server/src/main/java/org/eclipse/openvsx/search/RelevanceService.java @@ -26,8 +26,8 @@ import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.time.Duration; import java.time.LocalDateTime; import java.util.Optional; @@ -162,8 +162,7 @@ private boolean isVerified(ExtensionVersion extVersion) { return false; var user = extVersion.getPublishedWith().getUser(); var namespace = extVersion.getExtension().getNamespace(); - return repositories.countMemberships(namespace, NamespaceMembership.ROLE_OWNER) > 0 - && repositories.countMemberships(user, namespace) > 0; + return repositories.isVerified(namespace, user); } public static class SearchStats { diff --git a/server/src/main/java/org/eclipse/openvsx/search/SearchConfig.java b/server/src/main/java/org/eclipse/openvsx/search/SearchConfig.java index b1bd40622..8adb1debe 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/SearchConfig.java +++ b/server/src/main/java/org/eclipse/openvsx/search/SearchConfig.java @@ -9,32 +9,27 @@ ********************************************************************************/ package org.eclipse.openvsx.search; -import java.io.File; -import java.io.IOException; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; - -import javax.net.ssl.SSLContext; - +import org.apache.commons.lang3.StringUtils; import org.apache.http.ssl.SSLContextBuilder; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.common.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.RestClients; -import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration; + +import javax.net.ssl.SSLContext; +import java.io.File; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; @Configuration @Profile("!test") -public class SearchConfig extends AbstractElasticsearchConfiguration { +public class SearchConfig extends ElasticsearchConfiguration { protected final Logger logger = LoggerFactory.getLogger(SearchConfig.class); @@ -54,7 +49,7 @@ public class SearchConfig extends AbstractElasticsearchConfiguration { String trustStore; /** - * Name from https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#sslcontext-algorithms + * Name from https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#sslcontext-algorithms */ @Value("${ovsx.elasticsearch.truststoreProtocol:TLSv1.2}") String trustStoreProtocol; @@ -63,21 +58,17 @@ public class SearchConfig extends AbstractElasticsearchConfiguration { String trustStorePassword; @Override - public RestHighLevelClient elasticsearchClient() { + public ClientConfiguration clientConfiguration() { var builder = ClientConfiguration.builder(); - var connected = Strings.isNullOrEmpty(searchHost) + var connected = StringUtils.isEmpty(searchHost) ? builder.connectedToLocalhost() : builder.connectedTo(searchHost); var secure = useSsl ? connected.usingSsl(sslContext()) : connected; - var authenticated = Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(password) + var authenticated = StringUtils.isEmpty(username) || StringUtils.isEmpty(password) ? secure : secure.withBasicAuth(username, password); - return RestClients.create(authenticated.build()).rest(); - } - @Bean(destroyMethod = "close") - public RestClient restClient() { - return elasticsearchClient().getLowLevelClient(); + return authenticated.build(); } /** @@ -85,9 +76,9 @@ public RestClient restClient() { * are non empty. Returns {@link SSLContext#getDefault() default} SSLContext otherwise. */ private SSLContext sslContext() { - if (!Strings.isNullOrEmpty(trustStore)) { + if (!StringUtils.isEmpty(trustStore)) { var sslContextBuilder = SSLContextBuilder.create().setProtocol(trustStoreProtocol); - if (!Strings.isNullOrEmpty(trustStorePassword)) { + if (!StringUtils.isEmpty(trustStorePassword)) { try { sslContextBuilder.loadTrustMaterial(new File(trustStore), trustStorePassword.toCharArray()); } catch(NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) { @@ -112,5 +103,4 @@ private SSLContext sslContext() { throw new RuntimeException("Error while getting default SSLContext", e); } } - } \ No newline at end of file diff --git a/server/src/main/java/org/eclipse/openvsx/search/SearchUtilService.java b/server/src/main/java/org/eclipse/openvsx/search/SearchUtilService.java index fde318695..f9d7b0cfb 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/SearchUtilService.java +++ b/server/src/main/java/org/eclipse/openvsx/search/SearchUtilService.java @@ -15,6 +15,7 @@ import org.springframework.data.elasticsearch.core.SearchHits; import org.eclipse.openvsx.entities.Extension; +import java.util.Collection; import java.util.List; /** @@ -77,6 +78,9 @@ public void updateSearchEntry(Extension extension) { getImplementation().updateSearchEntry(extension); } + @Override + public void removeSearchEntries(Collection ids) { getImplementation().removeSearchEntries(ids); } + @Override public void removeSearchEntry(Extension extension) { getImplementation().removeSearchEntry(extension); diff --git a/server/src/main/java/org/eclipse/openvsx/security/CustomAuthenticationSuccessHandler.java b/server/src/main/java/org/eclipse/openvsx/security/CustomAuthenticationSuccessHandler.java index 1cb31e3ea..4981eb277 100644 --- a/server/src/main/java/org/eclipse/openvsx/security/CustomAuthenticationSuccessHandler.java +++ b/server/src/main/java/org/eclipse/openvsx/security/CustomAuthenticationSuccessHandler.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx.security; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.eclipse.openvsx.util.UrlUtil; import org.springframework.security.core.Authentication; diff --git a/server/src/main/java/org/eclipse/openvsx/security/OAuth2UserServices.java b/server/src/main/java/org/eclipse/openvsx/security/OAuth2UserServices.java index 82642e03d..1a69ee538 100644 --- a/server/src/main/java/org/eclipse/openvsx/security/OAuth2UserServices.java +++ b/server/src/main/java/org/eclipse/openvsx/security/OAuth2UserServices.java @@ -14,10 +14,9 @@ import java.util.Collection; import java.util.Collections; -import javax.persistence.EntityManager; - -import com.google.common.base.Strings; +import jakarta.persistence.EntityManager; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.UserService; import org.eclipse.openvsx.eclipse.EclipseService; import org.eclipse.openvsx.entities.UserData; @@ -115,7 +114,7 @@ public IdPrincipal loadUser(OAuth2UserRequest userRequest) { private IdPrincipal loadGitHubUser(OAuth2UserRequest userRequest) { var authUser = delegate.loadUser(userRequest); String loginName = authUser.getAttribute("login"); - if (Strings.isNullOrEmpty(loginName)) + if (StringUtils.isEmpty(loginName)) throw new CodedAuthException("Invalid login: missing 'login' field.", INVALID_GITHUB_USER); var userData = repositories.findUserByLoginName("github", loginName); if (userData == null) @@ -139,7 +138,7 @@ private IdPrincipal loadEclipseUser(OAuth2UserRequest userRequest) { try { var accessToken = userRequest.getAccessToken().getTokenValue(); var profile = eclipse.getUserProfile(accessToken); - if (Strings.isNullOrEmpty(profile.githubHandle)) + if (StringUtils.isEmpty(profile.githubHandle)) throw new CodedAuthException("Your Eclipse profile is missing a GitHub username.", ECLIPSE_MISSING_GITHUB_ID); if (!profile.githubHandle.equalsIgnoreCase(userData.getLoginName())) diff --git a/server/src/main/java/org/eclipse/openvsx/security/SecurityConfig.java b/server/src/main/java/org/eclipse/openvsx/security/SecurityConfig.java index 00a628e5e..641b28ba4 100644 --- a/server/src/main/java/org/eclipse/openvsx/security/SecurityConfig.java +++ b/server/src/main/java/org/eclipse/openvsx/security/SecurityConfig.java @@ -9,18 +9,25 @@ ********************************************************************************/ package org.eclipse.openvsx.security; +import org.apache.commons.lang3.StringUtils; 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.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfAuthenticationStrategy; +import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; -import com.google.common.base.Strings; - +@Configuration @EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { @Value("${ovsx.webui.url:}") String webuiUrl; @@ -31,52 +38,46 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${ovsx.webui.frontendRoutes:/extension/**,/namespace/**,/user-settings/**,/admin-dashboard/**}") String[] frontendRoutes; - @Override - protected void configure(HttpSecurity http) throws Exception { - var redirectUrl = Strings.isNullOrEmpty(webuiUrl) ? "/" : webuiUrl; - - http - .authorizeRequests() - .antMatchers("/*", "/login/**", "/oauth2/**", "/user", "/user/auth-error", "/logout", "/actuator/health/**", "/actuator/metrics", "/actuator/metrics/**", "/actuator/prometheus") - .permitAll() - .antMatchers("/api/*/*/review", "/api/*/*/review/delete", "/api/user/publish", "/api/user/namespace/create") - .authenticated() - .antMatchers("/api/**", "/vscode/**", "/documents/**", "/admin/report", "/admin/reports", "/admin/report/schedule") - .permitAll() - .antMatchers("/admin/**") - .hasAuthority("ROLE_ADMIN") - .antMatchers(frontendRoutes) - .permitAll() - .anyRequest() - .authenticated() - .and() - .cors() - .and() - .csrf() - .ignoringAntMatchers("/api/-/publish", "/api/-/namespace/create", "/api/-/query", "/admin/report/schedule", "/vscode/**") - .and() - .exceptionHandling() - // Respond with 403 status when the user is not logged in - .authenticationEntryPoint(new Http403ForbiddenEntryPoint()) - .and() - - .oauth2Login(configurer -> { - configurer.defaultSuccessUrl(redirectUrl); - configurer.successHandler(new CustomAuthenticationSuccessHandler(redirectUrl)); - configurer.failureUrl(redirectUrl + "?auth-error"); - configurer.userInfoEndpoint() - .oidcUserService(userServices.getOidc()) - .userService(userServices.getOauth2()); - }) - - .logout() - .logoutSuccessUrl(redirectUrl); + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + var redirectUrl = StringUtils.isEmpty(webuiUrl) ? "/" : webuiUrl; + return http.authorizeHttpRequests( + registry -> registry + .requestMatchers(antMatchers("/*", "/login/**", "/oauth2/**", "/user", "/user/auth-error", "/logout", "/actuator/health/**", "/actuator/metrics", "/actuator/metrics/**", "/actuator/prometheus", "/v3/api-docs/**", "/swagger-resources/**", "/swagger-ui/**", "/webjars/**")) + .permitAll() + .requestMatchers(antMatchers("/api/*/*/review", "/api/*/*/review/delete", "/api/user/publish", "/api/user/namespace/create")) + .authenticated() + .requestMatchers(antMatchers("/api/**", "/vscode/**", "/documents/**", "/admin/report", "/admin/reports", "/admin/report/schedule")) + .permitAll() + .requestMatchers(antMatchers("/admin/**")) + .hasAuthority("ROLE_ADMIN") + .requestMatchers(antMatchers(frontendRoutes)) + .permitAll() + .anyRequest() + .authenticated() + ) + .cors(configurer -> configurer.configure(http)) + .csrf(configurer -> { + configurer.ignoringRequestMatchers(antMatchers("/api/-/publish", "/api/-/namespace/create", "/api/-/query", "/admin/report/schedule", "/vscode/**")); + }) + .exceptionHandling(configurer -> configurer.authenticationEntryPoint(new Http403ForbiddenEntryPoint())) + .oauth2Login(configurer -> { + configurer.defaultSuccessUrl(redirectUrl); + configurer.successHandler(new CustomAuthenticationSuccessHandler(redirectUrl)); + configurer.failureUrl(redirectUrl + "?auth-error"); + configurer.userInfoEndpoint(customizer -> customizer.oidcUserService(userServices.getOidc()).userService(userServices.getOauth2())); + }) + .logout(configurer -> configurer.logoutSuccessUrl(redirectUrl)) + .build(); } - @Override - public void configure(WebSecurity web) throws Exception { - // Ignore resources required by Swagger API documentation - web.ignoring().antMatchers("/v3/api-docs/**", "/swagger-resources/**", "/swagger-ui/**", "/webjars/**"); - } + private RequestMatcher[] antMatchers(String... patterns) + { + var antMatchers = new RequestMatcher[patterns.length]; + for(var i = 0; i < patterns.length; i++) { + antMatchers[i] = AntPathRequestMatcher.antMatcher(patterns[i]); + } + return antMatchers; + } } \ No newline at end of file diff --git a/server/src/main/java/org/eclipse/openvsx/security/TokenService.java b/server/src/main/java/org/eclipse/openvsx/security/TokenService.java index ab763cbf2..aa6976824 100644 --- a/server/src/main/java/org/eclipse/openvsx/security/TokenService.java +++ b/server/src/main/java/org/eclipse/openvsx/security/TokenService.java @@ -12,7 +12,7 @@ import java.time.Instant; import java.util.Arrays; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/server/src/main/java/org/eclipse/openvsx/storage/AzureBlobStorageService.java b/server/src/main/java/org/eclipse/openvsx/storage/AzureBlobStorageService.java index 49adb3d2f..7bc5ba302 100644 --- a/server/src/main/java/org/eclipse/openvsx/storage/AzureBlobStorageService.java +++ b/server/src/main/java/org/eclipse/openvsx/storage/AzureBlobStorageService.java @@ -16,11 +16,10 @@ import com.azure.storage.blob.models.BlobHttpHeaders; import com.azure.storage.blob.models.BlobStorageException; import com.azure.storage.blob.models.CopyStatusType; -import com.google.common.base.Strings; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.FileResource; import org.eclipse.openvsx.entities.Namespace; -import org.eclipse.openvsx.util.TargetPlatform; import org.eclipse.openvsx.util.TempFile; import org.eclipse.openvsx.util.UrlUtil; import org.springframework.beans.factory.annotation.Value; @@ -52,7 +51,7 @@ public class AzureBlobStorageService implements IStorageService { @Override public boolean isEnabled() { - return !Strings.isNullOrEmpty(serviceEndpoint); + return !StringUtils.isEmpty(serviceEndpoint); } protected BlobContainerClient getContainerClient() { @@ -79,7 +78,7 @@ public void uploadNamespaceLogo(Namespace namespace) { } protected void uploadFile(byte[] content, String fileName, String blobName) { - if (Strings.isNullOrEmpty(serviceEndpoint)) { + if (StringUtils.isEmpty(serviceEndpoint)) { throw new IllegalStateException("Cannot upload file " + blobName + ": missing Azure blob service endpoint"); } @@ -108,7 +107,7 @@ public void uploadFile(FileResource resource, TempFile file) { } protected void uploadFile(TempFile file, String fileName, String blobName) { - if (Strings.isNullOrEmpty(serviceEndpoint)) { + if (StringUtils.isEmpty(serviceEndpoint)) { throw new IllegalStateException("Cannot upload file " + blobName + ": missing Azure blob service endpoint"); } @@ -138,7 +137,7 @@ public void removeNamespaceLogo(Namespace namespace) { } private void removeFile(String blobName) { - if (Strings.isNullOrEmpty(serviceEndpoint)) { + if (StringUtils.isEmpty(serviceEndpoint)) { throw new IllegalStateException("Cannot remove file " + blobName + ": missing Azure blob service endpoint"); } @@ -157,7 +156,7 @@ private void removeFile(String blobName) { @Override public URI getLocation(FileResource resource) { var blobName = getBlobName(resource); - if (Strings.isNullOrEmpty(serviceEndpoint)) { + if (StringUtils.isEmpty(serviceEndpoint)) { throw new IllegalStateException("Cannot determine location of file " + blobName + ": missing Azure blob service endpoint"); } @@ -184,7 +183,7 @@ protected String getBlobName(FileResource resource) { @Override public URI getNamespaceLogoLocation(Namespace namespace) { var blobName = getBlobName(namespace); - if (Strings.isNullOrEmpty(serviceEndpoint)) { + if (StringUtils.isEmpty(serviceEndpoint)) { throw new IllegalStateException("Cannot determine location of file " + blobName + ": missing Azure blob service endpoint"); } diff --git a/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountProcessor.java b/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountProcessor.java index 725d030c6..7085c0065 100644 --- a/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountProcessor.java +++ b/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountProcessor.java @@ -19,8 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; diff --git a/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountService.java b/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountService.java index b5163d112..72cb861e7 100644 --- a/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountService.java +++ b/server/src/main/java/org/eclipse/openvsx/storage/AzureDownloadCountService.java @@ -18,7 +18,7 @@ import com.azure.storage.blob.models.ListBlobsOptions; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.util.TempFile; import org.jobrunr.jobs.annotations.Job; import org.jobrunr.spring.annotations.Recurring; @@ -79,8 +79,8 @@ public class AzureDownloadCountService { * Indicates whether the download service is enabled by application config. */ public boolean isEnabled() { - var logsEnabled = !Strings.isNullOrEmpty(logsServiceEndpoint); - var storageEnabled = !Strings.isNullOrEmpty(storageServiceEndpoint); + var logsEnabled = !StringUtils.isEmpty(logsServiceEndpoint); + var storageEnabled = !StringUtils.isEmpty(storageServiceEndpoint); if(logsEnabled && !storageEnabled) { logger.warn("The ovsx.storage.azure.service-endpoint value must be set to enable AzureDownloadCountService"); } @@ -143,7 +143,7 @@ public void updateDownloadCounts() { } var continuationToken = response != null ? response.getContinuationToken() : ""; - iterableByPage = !Strings.isNullOrEmpty(continuationToken) ? blobs.iterableByPage(continuationToken) : null; + iterableByPage = !StringUtils.isEmpty(continuationToken) ? blobs.iterableByPage(continuationToken) : null; } logger.info("<< updateDownloadCounts"); diff --git a/server/src/main/java/org/eclipse/openvsx/storage/GoogleCloudStorageService.java b/server/src/main/java/org/eclipse/openvsx/storage/GoogleCloudStorageService.java index b530b3111..ad8090c78 100644 --- a/server/src/main/java/org/eclipse/openvsx/storage/GoogleCloudStorageService.java +++ b/server/src/main/java/org/eclipse/openvsx/storage/GoogleCloudStorageService.java @@ -13,7 +13,6 @@ import com.google.cloud.storage.BlobInfo; import com.google.cloud.storage.Storage; import com.google.cloud.storage.StorageOptions; -import com.google.common.base.Strings; import org.apache.commons.lang3.ArrayUtils; import org.eclipse.openvsx.entities.FileResource; import org.eclipse.openvsx.entities.Namespace; @@ -23,6 +22,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.util.Pair; import org.springframework.stereotype.Component; +import org.apache.commons.lang3.StringUtils; import java.io.FileOutputStream; import java.io.IOException; @@ -46,13 +46,13 @@ public class GoogleCloudStorageService implements IStorageService { @Override public boolean isEnabled() { - return !Strings.isNullOrEmpty(bucketId); + return !StringUtils.isEmpty(bucketId); } protected Storage getStorage() { if (storage == null) { StorageOptions options; - if (Strings.isNullOrEmpty(projectId)) { + if (StringUtils.isEmpty(projectId)) { options = StorageOptions.getDefaultInstance(); } else { options = StorageOptions.newBuilder() @@ -67,7 +67,7 @@ protected Storage getStorage() { @Override public void uploadFile(FileResource resource) { var objectId = getObjectId(resource); - if (Strings.isNullOrEmpty(bucketId)) { + if (StringUtils.isEmpty(bucketId)) { throw new IllegalStateException("Cannot upload file " + objectId + ": missing Google bucket id"); } @@ -78,7 +78,7 @@ public void uploadFile(FileResource resource) { @Override public void uploadNamespaceLogo(Namespace namespace) { var objectId = getObjectId(namespace); - if (Strings.isNullOrEmpty(bucketId)) { + if (StringUtils.isEmpty(bucketId)) { throw new IllegalStateException("Cannot upload file " + objectId + ": missing Google bucket id"); } @@ -101,7 +101,7 @@ protected void uploadFile(byte[] content, String fileName, String objectId) { @Override public void uploadFile(FileResource resource, TempFile file) { var objectId = getObjectId(resource); - if (Strings.isNullOrEmpty(bucketId)) { + if (StringUtils.isEmpty(bucketId)) { throw new IllegalStateException("Cannot upload file " + objectId + ": missing Google bucket id"); } @@ -144,7 +144,7 @@ public void removeNamespaceLogo(Namespace namespace) { } private void removeFile(String objectId) { - if (Strings.isNullOrEmpty(bucketId)) { + if (StringUtils.isEmpty(bucketId)) { throw new IllegalStateException("Cannot remove file " + objectId + ": missing Google bucket id"); } @@ -154,7 +154,7 @@ private void removeFile(String objectId) { @Override public URI getLocation(FileResource resource) { - if (Strings.isNullOrEmpty(bucketId)) { + if (StringUtils.isEmpty(bucketId)) { throw new IllegalStateException("Cannot determine location of file " + resource.getName() + ": missing Google bucket id"); } @@ -177,7 +177,7 @@ protected String getObjectId(FileResource resource) { @Override public URI getNamespaceLogoLocation(Namespace namespace) { - if (Strings.isNullOrEmpty(bucketId)) { + if (StringUtils.isEmpty(bucketId)) { throw new IllegalStateException("Cannot determine location of file " + namespace.getLogoName() + ": missing Google bucket id"); } diff --git a/server/src/main/java/org/eclipse/openvsx/storage/StorageMigration.java b/server/src/main/java/org/eclipse/openvsx/storage/StorageMigration.java index 783f61698..1d8fb397a 100644 --- a/server/src/main/java/org/eclipse/openvsx/storage/StorageMigration.java +++ b/server/src/main/java/org/eclipse/openvsx/storage/StorageMigration.java @@ -24,7 +24,7 @@ import org.springframework.transaction.support.TransactionTemplate; import org.springframework.web.client.RestTemplate; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; diff --git a/server/src/main/java/org/eclipse/openvsx/storage/StorageUtilService.java b/server/src/main/java/org/eclipse/openvsx/storage/StorageUtilService.java index 82f7335d2..4cdfe552e 100644 --- a/server/src/main/java/org/eclipse/openvsx/storage/StorageUtilService.java +++ b/server/src/main/java/org/eclipse/openvsx/storage/StorageUtilService.java @@ -9,8 +9,8 @@ ********************************************************************************/ package org.eclipse.openvsx.storage; -import com.google.common.base.Strings; import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.cache.CacheService; import org.eclipse.openvsx.entities.Download; import org.eclipse.openvsx.entities.ExtensionVersion; @@ -30,8 +30,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.io.IOException; import java.net.URI; import java.nio.file.Files; @@ -108,7 +108,7 @@ public String getActiveStorageType() { storageTypes.add(STORAGE_GOOGLE); if (azureStorage.isEnabled()) storageTypes.add(STORAGE_AZURE); - if (!Strings.isNullOrEmpty(primaryService)) { + if (!StringUtils.isEmpty(primaryService)) { if (!storageTypes.contains(primaryService)) throw new RuntimeException("The selected primary storage service is not available."); return primaryService; diff --git a/server/src/main/java/org/eclipse/openvsx/util/NamingUtil.java b/server/src/main/java/org/eclipse/openvsx/util/NamingUtil.java index 8c200345d..142a211cd 100644 --- a/server/src/main/java/org/eclipse/openvsx/util/NamingUtil.java +++ b/server/src/main/java/org/eclipse/openvsx/util/NamingUtil.java @@ -9,7 +9,7 @@ * ****************************************************************************** */ package org.eclipse.openvsx.util; -import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.adapter.ExtensionQueryResult; import org.eclipse.openvsx.entities.Extension; import org.eclipse.openvsx.entities.ExtensionVersion; @@ -59,10 +59,10 @@ public static String toLogFormat(String namespace, String extension, String vers public static String toLogFormat(String namespace, String extension, String targetPlatform, String version) { var name = toExtensionId(namespace, extension); - if(!Strings.isNullOrEmpty(version)) { + if(!StringUtils.isEmpty(version)) { name += " " + version; } - if(!Strings.isNullOrEmpty(targetPlatform) && !TargetPlatform.isUniversal(targetPlatform)) { + if(!StringUtils.isEmpty(targetPlatform) && !TargetPlatform.isUniversal(targetPlatform)) { name += " (" + targetPlatform + ")"; } diff --git a/server/src/main/java/org/eclipse/openvsx/util/UrlUtil.java b/server/src/main/java/org/eclipse/openvsx/util/UrlUtil.java index edb64b6ee..16f4feafa 100644 --- a/server/src/main/java/org/eclipse/openvsx/util/UrlUtil.java +++ b/server/src/main/java/org/eclipse/openvsx/util/UrlUtil.java @@ -10,8 +10,12 @@ package org.eclipse.openvsx.util; import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; +import java.util.stream.Collectors; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.entities.ExtensionVersion; import org.eclipse.openvsx.json.ExtensionJson; import org.springframework.util.AntPathMatcher; @@ -20,7 +24,7 @@ import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.util.UriUtils; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public final class UrlUtil { @@ -89,22 +93,20 @@ private static String[] createApiVersionSegments(String namespaceName, String ex * Create a URL pointing to an API path. */ public static String createApiUrl(String baseUrl, String... segments) { - var initialCapacity = baseUrl.length() + 8; - for (var segment : segments) { - initialCapacity += segment.length() + 1; + if(Arrays.stream(segments).anyMatch(Objects::isNull)) { + return null; } - var result = new StringBuilder(initialCapacity); - result.append(baseUrl); - for (var segment : segments) { - if (segment == null) - return null; - if (segment.isEmpty()) - continue; - if (result.length() == 0 || result.charAt(result.length() - 1) != '/') - result.append('/'); - result.append(UriUtils.encodePathSegment(segment, StandardCharsets.UTF_8)); + + var path = Arrays.stream(segments) + .filter(StringUtils::isNotEmpty) + .map(segment -> UriUtils.encodePathSegment(segment, StandardCharsets.UTF_8)) + .collect(Collectors.joining("/")); + + if (baseUrl.isEmpty() || baseUrl.charAt(baseUrl.length() - 1) != '/') { + baseUrl += '/'; } - return result.toString(); + + return baseUrl + path; } /** diff --git a/server/src/main/java/org/eclipse/openvsx/util/VersionService.java b/server/src/main/java/org/eclipse/openvsx/util/VersionService.java index 44deef327..bed255b12 100644 --- a/server/src/main/java/org/eclipse/openvsx/util/VersionService.java +++ b/server/src/main/java/org/eclipse/openvsx/util/VersionService.java @@ -15,8 +15,8 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.util.List; import static org.eclipse.openvsx.cache.CacheService.*; diff --git a/server/src/main/java/org/eclipse/openvsx/web/CachedBodyHttpServletRequest.java b/server/src/main/java/org/eclipse/openvsx/web/CachedBodyHttpServletRequest.java index bee786717..26f7d1491 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/CachedBodyHttpServletRequest.java +++ b/server/src/main/java/org/eclipse/openvsx/web/CachedBodyHttpServletRequest.java @@ -11,9 +11,9 @@ import org.springframework.util.StreamUtils; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/server/src/main/java/org/eclipse/openvsx/web/CachedBodyServletInputStream.java b/server/src/main/java/org/eclipse/openvsx/web/CachedBodyServletInputStream.java index e6ace1992..54506a912 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/CachedBodyServletInputStream.java +++ b/server/src/main/java/org/eclipse/openvsx/web/CachedBodyServletInputStream.java @@ -9,8 +9,8 @@ * ****************************************************************************** */ package org.eclipse.openvsx.web; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; diff --git a/server/src/main/java/org/eclipse/openvsx/web/DocumentationConfig.java b/server/src/main/java/org/eclipse/openvsx/web/DocumentationConfig.java index bb2e584ee..490a57fa2 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/DocumentationConfig.java +++ b/server/src/main/java/org/eclipse/openvsx/web/DocumentationConfig.java @@ -13,8 +13,8 @@ import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.media.Schema; -import org.springdoc.core.GroupedOpenApi; -import org.springdoc.core.customizers.OpenApiCustomiser; +import org.springdoc.core.models.GroupedOpenApi; +import org.springdoc.core.customizers.OpenApiCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -25,16 +25,16 @@ public class DocumentationConfig { @Bean - public GroupedOpenApi api(OpenApiCustomiser sortSchemasAlphabetically) { + public GroupedOpenApi api(OpenApiCustomizer sortSchemasAlphabetically) { return GroupedOpenApi.builder() .group("default") .pathsToMatch("/api/**") - .addOpenApiCustomiser(sortSchemasAlphabetically) + .addOpenApiCustomizer(sortSchemasAlphabetically) .build(); } @Bean - public OpenApiCustomiser sortSchemasAlphabetically() { + public OpenApiCustomizer sortSchemasAlphabetically() { return openApi -> { Map schemas = openApi.getComponents().getSchemas(); openApi.getComponents().setSchemas(new TreeMap<>(schemas)); diff --git a/server/src/main/java/org/eclipse/openvsx/web/LongRunningRequestFilter.java b/server/src/main/java/org/eclipse/openvsx/web/LongRunningRequestFilter.java index e5e2781fb..3ea4d9275 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/LongRunningRequestFilter.java +++ b/server/src/main/java/org/eclipse/openvsx/web/LongRunningRequestFilter.java @@ -15,10 +15,10 @@ import org.springframework.util.StreamUtils; import org.springframework.web.filter.OncePerRequestFilter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/server/src/main/java/org/eclipse/openvsx/web/ShallowEtagHeaderFilter.java b/server/src/main/java/org/eclipse/openvsx/web/ShallowEtagHeaderFilter.java index f4e48560c..88901701f 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/ShallowEtagHeaderFilter.java +++ b/server/src/main/java/org/eclipse/openvsx/web/ShallowEtagHeaderFilter.java @@ -9,8 +9,8 @@ * ****************************************************************************** */ package org.eclipse.openvsx.web; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; public class ShallowEtagHeaderFilter extends org.springframework.web.filter.ShallowEtagHeaderFilter { diff --git a/server/src/main/java/org/eclipse/openvsx/web/SitemapController.java b/server/src/main/java/org/eclipse/openvsx/web/SitemapController.java index d945e1431..3e3daba3b 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/SitemapController.java +++ b/server/src/main/java/org/eclipse/openvsx/web/SitemapController.java @@ -9,36 +9,31 @@ ********************************************************************************/ package org.eclipse.openvsx.web; -import java.net.URI; -import java.time.format.DateTimeFormatter; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import javax.transaction.Transactional; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import com.google.common.base.Strings; - -import org.apache.commons.lang3.ArrayUtils; -import org.eclipse.openvsx.ExtensionService; -import org.eclipse.openvsx.entities.ExtensionVersion; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.repositories.RepositoryService; -import org.eclipse.openvsx.util.TargetPlatform; import org.eclipse.openvsx.util.UrlUtil; import org.eclipse.openvsx.util.VersionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; +import org.springframework.http.CacheControl; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.net.URI; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.TimeUnit; + @RestController public class SitemapController { @@ -94,7 +89,7 @@ public ResponseEntity getSitemap() throws ParserConfigura } private String getBaseUrl() { - if (Strings.isNullOrEmpty(webuiUrl)) + if (StringUtils.isEmpty(webuiUrl)) return UrlUtil.getBaseUrl(); else if (URI.create(webuiUrl).isAbsolute()) return webuiUrl; diff --git a/server/src/main/java/org/eclipse/openvsx/web/WebConfig.java b/server/src/main/java/org/eclipse/openvsx/web/WebConfig.java index 8835c85c6..d2a06c397 100644 --- a/server/src/main/java/org/eclipse/openvsx/web/WebConfig.java +++ b/server/src/main/java/org/eclipse/openvsx/web/WebConfig.java @@ -11,8 +11,8 @@ import java.net.URI; +import org.apache.commons.lang3.StringUtils; import org.eclipse.openvsx.mirror.MirrorExtensionHandlerInterceptor; -import org.elasticsearch.common.Strings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -35,7 +35,7 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { - if (!Strings.isNullOrEmpty(webuiUrl) && URI.create(webuiUrl).isAbsolute()) { + if (!StringUtils.isEmpty(webuiUrl) && URI.create(webuiUrl).isAbsolute()) { // The Web UI is given with an absolute URL, so we need to enable CORS with credentials. var authorizedEndpoints = new String[] { "/user/**", diff --git a/server/src/main/resources/db/migration/V1_40__Entity_Sequencies.sql b/server/src/main/resources/db/migration/V1_40__Entity_Sequencies.sql new file mode 100644 index 000000000..322c547a2 --- /dev/null +++ b/server/src/main/resources/db/migration/V1_40__Entity_Sequencies.sql @@ -0,0 +1,41 @@ +CREATE SEQUENCE admin_statistics_seq INCREMENT 50 OWNED BY public.admin_statistics.id; +SELECT SETVAL('admin_statistics_seq', (SELECT COALESCE(MAX(id), 1) FROM admin_statistics)::BIGINT); + +CREATE SEQUENCE azure_download_count_processed_item_seq INCREMENT 50 OWNED BY public.azure_download_count_processed_item.id; +SELECT SETVAL('azure_download_count_processed_item_seq', (SELECT COALESCE(MAX(id), 1) FROM azure_download_count_processed_item)::BIGINT); + +ALTER SEQUENCE download_id_seq RENAME TO download_seq; +ALTER SEQUENCE download_seq INCREMENT 50; + +CREATE SEQUENCE extension_seq INCREMENT 50 OWNED BY public.extension.id; +SELECT SETVAL('extension_seq', (SELECT COALESCE(MAX(id), 1) FROM extension)::BIGINT); + +CREATE SEQUENCE extension_review_seq INCREMENT 50 OWNED BY public.extension_review.id; +SELECT SETVAL('extension_review_seq', (SELECT COALESCE(MAX(id), 1) FROM extension_review)::BIGINT); + +CREATE SEQUENCE extension_version_seq INCREMENT 50 OWNED BY public.extension_version.id; +SELECT SETVAL('extension_version_seq', (SELECT COALESCE(MAX(id), 1) FROM extension_version)::BIGINT); + +ALTER SEQUENCE file_resource_id_seq RENAME TO file_resource_seq; +ALTER SEQUENCE file_resource_seq INCREMENT 50; + +CREATE SEQUENCE migration_item_seq INCREMENT 50 OWNED BY public.migration_item.id; +SELECT SETVAL('migration_item_seq', (SELECT COALESCE(MAX(id), 1) FROM migration_item)::BIGINT); + +CREATE SEQUENCE namespace_seq INCREMENT 50 OWNED BY public.namespace.id; +SELECT SETVAL('namespace_seq', (SELECT COALESCE(MAX(id), 1) FROM namespace)::BIGINT); + +CREATE SEQUENCE namespace_membership_seq INCREMENT 50 OWNED BY public.namespace_membership.id; +SELECT SETVAL('namespace_membership_seq', (SELECT COALESCE(MAX(id), 1) FROM namespace_membership)::BIGINT); + +CREATE SEQUENCE persisted_log_seq INCREMENT 50 OWNED BY public.persisted_log.id; +SELECT SETVAL('persisted_log_seq', (SELECT COALESCE(MAX(id), 1) FROM persisted_log)::BIGINT); + +CREATE SEQUENCE personal_access_token_seq INCREMENT 50 OWNED BY public.personal_access_token.id; +SELECT SETVAL('personal_access_token_seq', (SELECT COALESCE(MAX(id), 1) FROM personal_access_token)::BIGINT); + +CREATE SEQUENCE signature_key_pair_seq INCREMENT 50 OWNED BY public.signature_key_pair.id; +SELECT SETVAL('signature_key_pair_seq', (SELECT COALESCE(MAX(id), 1) FROM signature_key_pair)::BIGINT); + +CREATE SEQUENCE user_data_seq INCREMENT 50 OWNED BY public.user_data.id; +SELECT SETVAL('user_data_seq', (SELECT COALESCE(MAX(id), 1) FROM user_data)::BIGINT); \ No newline at end of file diff --git a/server/src/test/java/org/eclipse/openvsx/IntegrationTest.java b/server/src/test/java/org/eclipse/openvsx/IntegrationTest.java index 716bf7006..2cd745635 100644 --- a/server/src/test/java/org/eclipse/openvsx/IntegrationTest.java +++ b/server/src/test/java/org/eclipse/openvsx/IntegrationTest.java @@ -22,7 +22,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpStatus; import org.springframework.test.context.ActiveProfiles; diff --git a/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java b/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java index 2c0be17b5..dcab83182 100644 --- a/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java +++ b/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java @@ -12,6 +12,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import jakarta.persistence.EntityManager; import org.eclipse.openvsx.adapter.VSCodeIdService; import org.eclipse.openvsx.cache.CacheService; import org.eclipse.openvsx.cache.ExtensionJsonCacheKeyGenerator; @@ -27,6 +28,7 @@ import org.eclipse.openvsx.search.ISearchService; import org.eclipse.openvsx.search.SearchUtilService; import org.eclipse.openvsx.security.OAuth2UserServices; +import org.eclipse.openvsx.security.SecurityConfig; import org.eclipse.openvsx.security.TokenService; import org.eclipse.openvsx.storage.AzureBlobStorageService; import org.eclipse.openvsx.storage.AzureDownloadCountService; @@ -46,6 +48,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -58,7 +61,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityManager; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.LocalDateTime; @@ -2055,14 +2057,14 @@ private List mockSearch() { var entry1 = new ExtensionSearch(); entry1.id = 1; var searchHit = new SearchHit<>("0", "1", null, 1.0f, null, null, null, null, null, null, entry1); - var searchHits = new SearchHitsImpl<>(1, TotalHitsRelation.EQUAL_TO, 1.0f, "1", List.of(searchHit), null, null); + var searchHits = new SearchHitsImpl<>(1, TotalHitsRelation.EQUAL_TO, 1.0f, "1", null, List.of(searchHit), null, null); Mockito.when(search.isEnabled()) .thenReturn(true); var searchOptions = new ISearchService.Options("foo", null, null, 10, 0, "desc", "relevance", false); Mockito.when(search.search(searchOptions)) .thenReturn(searchHits); - Mockito.when(entityManager.find(Extension.class, 1L)) - .thenReturn(extension); + Mockito.when(repositories.findExtensions(Set.of(extension.getId()))) + .thenReturn(Streamable.of(extension)); return Arrays.asList(extension); } @@ -2126,8 +2128,8 @@ private void mockForPublish(String mode) { .thenReturn(1L); Mockito.when(repositories.findMembership(token.getUser(), namespace)) .thenReturn(ownerMem); - Mockito.when(repositories.countMemberships(token.getUser(), namespace)) - .thenReturn(1L); + Mockito.when(repositories.isVerified(namespace, token.getUser())) + .thenReturn(true); } else if (mode.equals("contributor") || mode.equals("sole-contributor") || mode.equals("existing")) { var contribMem = new NamespaceMembership(); contribMem.setUser(token.getUser()); @@ -2135,8 +2137,8 @@ private void mockForPublish(String mode) { contribMem.setRole(NamespaceMembership.ROLE_CONTRIBUTOR); Mockito.when(repositories.findMembership(token.getUser(), namespace)) .thenReturn(contribMem); - Mockito.when(repositories.countMemberships(token.getUser(), namespace)) - .thenReturn(1L); + Mockito.when(repositories.isVerified(namespace, token.getUser())) + .thenReturn(true); if (mode.equals("contributor")) { var otherUser = new UserData(); otherUser.setLoginName("other_user"); @@ -2146,13 +2148,13 @@ private void mockForPublish(String mode) { ownerMem.setRole(NamespaceMembership.ROLE_OWNER); Mockito.when(repositories.findMemberships(namespace, NamespaceMembership.ROLE_OWNER)) .thenReturn(Streamable.of(ownerMem)); - Mockito.when(repositories.countMemberships(namespace, NamespaceMembership.ROLE_OWNER)) - .thenReturn(1L); + Mockito.when(repositories.isVerified(namespace, token.getUser())) + .thenReturn(true); } else { Mockito.when(repositories.findMemberships(namespace, NamespaceMembership.ROLE_OWNER)) .thenReturn(Streamable.empty()); - Mockito.when(repositories.countMemberships(namespace, NamespaceMembership.ROLE_OWNER)) - .thenReturn(0L); + Mockito.when(repositories.isVerified(namespace, token.getUser())) + .thenReturn(false); } } else if (mode.equals("privileged") || mode.equals("unrelated")) { var otherUser = new UserData(); @@ -2261,6 +2263,7 @@ private byte[] createExtensionPackage(String name, String version, String licens } @TestConfiguration + @Import(SecurityConfig.class) static class TestConfig { @Bean TransactionTemplate transactionTemplate() { diff --git a/server/src/test/java/org/eclipse/openvsx/TestSearchConfig.java b/server/src/test/java/org/eclipse/openvsx/TestSearchConfig.java index 857d32a8f..aec136ee1 100644 --- a/server/src/test/java/org/eclipse/openvsx/TestSearchConfig.java +++ b/server/src/test/java/org/eclipse/openvsx/TestSearchConfig.java @@ -9,25 +9,23 @@ ********************************************************************************/ package org.eclipse.openvsx; -import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.RestClients; -import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration; import org.testcontainers.elasticsearch.ElasticsearchContainer; @Configuration @Profile("test") -public class TestSearchConfig extends AbstractElasticsearchConfiguration { +public class TestSearchConfig extends ElasticsearchConfiguration { @Override - @SuppressWarnings("resource") - public RestHighLevelClient elasticsearchClient() { - var container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.11.0"); + public ClientConfiguration clientConfiguration() { + var container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.7.1") + .withEnv("discovery.type", "single-node") + .withEnv("xpack.security.enabled", "false"); + container.start(); - var config = ClientConfiguration.create(container.getHttpHostAddress()); - return RestClients.create(config).rest(); + return ClientConfiguration.create(container.getHttpHostAddress()); } - } \ No newline at end of file diff --git a/server/src/test/java/org/eclipse/openvsx/TestService.java b/server/src/test/java/org/eclipse/openvsx/TestService.java index c69ab6e53..0057b61f5 100644 --- a/server/src/test/java/org/eclipse/openvsx/TestService.java +++ b/server/src/test/java/org/eclipse/openvsx/TestService.java @@ -11,8 +11,8 @@ import java.time.LocalDateTime; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import org.eclipse.openvsx.entities.PersonalAccessToken; import org.eclipse.openvsx.entities.UserData; diff --git a/server/src/test/java/org/eclipse/openvsx/UserAPITest.java b/server/src/test/java/org/eclipse/openvsx/UserAPITest.java index 563b74023..cd8d85ceb 100644 --- a/server/src/test/java/org/eclipse/openvsx/UserAPITest.java +++ b/server/src/test/java/org/eclipse/openvsx/UserAPITest.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.function.Consumer; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import org.eclipse.openvsx.cache.CacheService; import org.eclipse.openvsx.cache.LatestExtensionVersionCacheKeyGenerator; @@ -38,6 +38,7 @@ import org.eclipse.openvsx.json.UserJson; import org.eclipse.openvsx.repositories.RepositoryService; import org.eclipse.openvsx.security.OAuth2UserServices; +import org.eclipse.openvsx.security.SecurityConfig; import org.eclipse.openvsx.security.TokenService; import org.eclipse.openvsx.storage.StorageUtilService; import org.eclipse.openvsx.util.VersionService; @@ -50,6 +51,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.data.util.Streamable; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.test.web.servlet.MockMvc; @@ -547,6 +549,7 @@ private String errorJson(String message) throws JsonProcessingException { } @TestConfiguration + @Import(SecurityConfig.class) static class TestConfig { @Bean TransactionTemplate transactionTemplate() { diff --git a/server/src/test/java/org/eclipse/openvsx/adapter/VSCodeAPITest.java b/server/src/test/java/org/eclipse/openvsx/adapter/VSCodeAPITest.java index e95308ce9..a3b2f5d17 100644 --- a/server/src/test/java/org/eclipse/openvsx/adapter/VSCodeAPITest.java +++ b/server/src/test/java/org/eclipse/openvsx/adapter/VSCodeAPITest.java @@ -23,7 +23,7 @@ import java.util.*; import java.util.stream.Collectors; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -43,6 +43,7 @@ import org.eclipse.openvsx.search.ISearchService; import org.eclipse.openvsx.search.SearchUtilService; import org.eclipse.openvsx.security.OAuth2UserServices; +import org.eclipse.openvsx.security.SecurityConfig; import org.eclipse.openvsx.security.TokenService; import org.eclipse.openvsx.storage.AzureBlobStorageService; import org.eclipse.openvsx.storage.AzureDownloadCountService; @@ -58,6 +59,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHitsImpl; import org.springframework.data.elasticsearch.core.TotalHitsRelation; @@ -643,7 +645,7 @@ private Extension mockSearch(String targetPlatform, String namespaceName, boolea List> searchResults = !builtInExtensionNamespace.equals(namespaceName) ? Collections.singletonList(new SearchHit<>("0", "1", null, 1.0f, null, null, null, null, null, null, entry1)) : Collections.emptyList(); - var searchHits = new SearchHitsImpl<>(searchResults.size(), TotalHitsRelation.EQUAL_TO, 1.0f, "1", + var searchHits = new SearchHitsImpl<>(searchResults.size(), TotalHitsRelation.EQUAL_TO, 1.0f, "1", null, searchResults, null, null); Mockito.when(integrityService.isEnabled()) @@ -907,6 +909,7 @@ private String file(String name) throws UnsupportedEncodingException, IOExceptio } @TestConfiguration + @Import(SecurityConfig.class) static class TestConfig { @Bean IExtensionQueryRequestHandler extensionQueryRequestHandler(LocalVSCodeService local, UpstreamVSCodeService upstream) { diff --git a/server/src/test/java/org/eclipse/openvsx/admin/AdminAPITest.java b/server/src/test/java/org/eclipse/openvsx/admin/AdminAPITest.java index 9376ee912..d0a0c8a40 100644 --- a/server/src/test/java/org/eclipse/openvsx/admin/AdminAPITest.java +++ b/server/src/test/java/org/eclipse/openvsx/admin/AdminAPITest.java @@ -24,6 +24,7 @@ import org.eclipse.openvsx.repositories.RepositoryService; import org.eclipse.openvsx.search.SearchUtilService; import org.eclipse.openvsx.security.OAuth2UserServices; +import org.eclipse.openvsx.security.SecurityConfig; import org.eclipse.openvsx.security.TokenService; import org.eclipse.openvsx.storage.AzureBlobStorageService; import org.eclipse.openvsx.storage.AzureDownloadCountService; @@ -41,6 +42,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; import org.springframework.data.util.Streamable; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -49,7 +51,7 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.transaction.support.TransactionTemplate; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import java.time.LocalDateTime; import java.util.*; import java.util.function.Consumer; @@ -1190,6 +1192,7 @@ private String errorJson(String message) throws JsonProcessingException { } @TestConfiguration + @Import(SecurityConfig.class) static class TestConfig { @Bean TransactionTemplate transactionTemplate() { diff --git a/server/src/test/java/org/eclipse/openvsx/cache/CacheServiceTest.java b/server/src/test/java/org/eclipse/openvsx/cache/CacheServiceTest.java index 63cfbaff8..272c1c01f 100644 --- a/server/src/test/java/org/eclipse/openvsx/cache/CacheServiceTest.java +++ b/server/src/test/java/org/eclipse/openvsx/cache/CacheServiceTest.java @@ -32,8 +32,8 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.Collections; diff --git a/server/src/test/java/org/eclipse/openvsx/eclipse/EclipseServiceTest.java b/server/src/test/java/org/eclipse/openvsx/eclipse/EclipseServiceTest.java index ea21fab44..a8769c7b1 100644 --- a/server/src/test/java/org/eclipse/openvsx/eclipse/EclipseServiceTest.java +++ b/server/src/test/java/org/eclipse/openvsx/eclipse/EclipseServiceTest.java @@ -18,7 +18,7 @@ import java.io.InputStreamReader; import java.util.Map; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import org.eclipse.openvsx.ExtensionService; import org.eclipse.openvsx.ExtensionValidator; diff --git a/server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java b/server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java index 8a91d7b67..ea789840e 100644 --- a/server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java +++ b/server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java @@ -19,8 +19,8 @@ import org.springframework.data.domain.PageRequest; import org.springframework.test.context.ActiveProfiles; -import javax.persistence.EntityManager; -import javax.transaction.Transactional; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import java.lang.reflect.Modifier; import java.time.LocalDateTime; import java.util.List; @@ -87,7 +87,7 @@ void testExecuteQueries() { () -> repositories.countExtensions(), () -> repositories.countExtensions("name", "namespace"), () -> repositories.countMemberships(namespace, "role"), - () -> repositories.countMemberships(userData, namespace), + () -> repositories.isVerified(namespace, userData), () -> repositories.countNamespaces(), () -> repositories.countPublishersThatClaimedNamespaceOwnership(NOW), () -> repositories.countUsers(), diff --git a/server/src/test/java/org/eclipse/openvsx/search/DatabaseSearchServiceTest.java b/server/src/test/java/org/eclipse/openvsx/search/DatabaseSearchServiceTest.java index ecd52432a..389b05dbb 100644 --- a/server/src/test/java/org/eclipse/openvsx/search/DatabaseSearchServiceTest.java +++ b/server/src/test/java/org/eclipse/openvsx/search/DatabaseSearchServiceTest.java @@ -32,7 +32,7 @@ import org.springframework.data.util.Streamable; import org.springframework.test.context.junit.jupiter.SpringExtension; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; @ExtendWith(SpringExtension.class) public class DatabaseSearchServiceTest { @@ -333,8 +333,7 @@ private Extension mockExtension(String name, double averageRating, long ratingCo var token = new PersonalAccessToken(); token.setUser(user); extVer.setPublishedWith(token); - var isUnrelated = false; - Mockito.when(repositories.countMemberships(user, namespace)).thenReturn(isUnrelated ? 0l : 1l); + Mockito.when(repositories.isVerified(namespace, user)).thenReturn(false); return extension; } diff --git a/server/src/test/java/org/eclipse/openvsx/search/ElasticSearchServiceTest.java b/server/src/test/java/org/eclipse/openvsx/search/ElasticSearchServiceTest.java index c7e458ffc..5597d244e 100644 --- a/server/src/test/java/org/eclipse/openvsx/search/ElasticSearchServiceTest.java +++ b/server/src/test/java/org/eclipse/openvsx/search/ElasticSearchServiceTest.java @@ -30,7 +30,7 @@ import org.springframework.data.util.Streamable; import org.springframework.test.context.junit.jupiter.SpringExtension; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -246,8 +246,6 @@ private Extension mockExtension(String name, String namespaceName, String userNa var namespace = new Namespace(); namespace.setName(namespaceName); extension.setNamespace(namespace); - Mockito.when(repositories.countMemberships(namespace, NamespaceMembership.ROLE_OWNER)) - .thenReturn(isUnverified ? 0L : 1L); var extVer = new ExtensionVersion(); extVer.setTargetPlatform(TargetPlatform.NAME_UNIVERSAL); extVer.setTimestamp(timestamp); @@ -259,8 +257,8 @@ private Extension mockExtension(String name, String namespaceName, String userNa var token = new PersonalAccessToken(); token.setUser(user); extVer.setPublishedWith(token); - Mockito.when(repositories.countMemberships(user, namespace)) - .thenReturn(isUnrelated ? 0L : 1L); + Mockito.when(repositories.isVerified(namespace, user)) + .thenReturn(!isUnverified && !isUnrelated); return extension; } diff --git a/server/src/test/java/org/eclipse/openvsx/util/UrlUtilTest.java b/server/src/test/java/org/eclipse/openvsx/util/UrlUtilTest.java index 69d38266d..bc1b8f0b6 100644 --- a/server/src/test/java/org/eclipse/openvsx/util/UrlUtilTest.java +++ b/server/src/test/java/org/eclipse/openvsx/util/UrlUtilTest.java @@ -15,8 +15,7 @@ import java.util.ArrayList; import java.util.Collections; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/server/src/test/java/org/eclipse/openvsx/util/VersionServiceTest.java b/server/src/test/java/org/eclipse/openvsx/util/VersionServiceTest.java index ef6aebb15..1cc31ee42 100644 --- a/server/src/test/java/org/eclipse/openvsx/util/VersionServiceTest.java +++ b/server/src/test/java/org/eclipse/openvsx/util/VersionServiceTest.java @@ -20,7 +20,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit.jupiter.SpringExtension; -import javax.persistence.EntityManager; +import jakarta.persistence.EntityManager; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals;