diff --git a/server/src/main/java/org/eclipse/openvsx/ExtensionService.java b/server/src/main/java/org/eclipse/openvsx/ExtensionService.java index a39ba2596..2c57003c8 100644 --- a/server/src/main/java/org/eclipse/openvsx/ExtensionService.java +++ b/server/src/main/java/org/eclipse/openvsx/ExtensionService.java @@ -207,6 +207,9 @@ public void reactivateExtensions(UserData user) { var affectedExtensions = new LinkedHashSet(); var versions = repositories.findVersionsByUser(user, false); for (var version : versions) { + if (version.getState() == ExtensionVersion.State.DELETED) { + continue; + } version.setActive(true); affectedExtensions.add(version.getExtension()); } @@ -225,10 +228,20 @@ public ResultJson deleteExtension( var results = new ArrayList(); if(repositories.isDeleteAllVersions(namespaceName, extensionName, targetVersions, user)) { var extension = repositories.findExtension(extensionName, namespaceName); + if (extension == null || repositories.countVersions(namespaceName, extensionName) == 0) { + var message = "Extension not found: " + NamingUtil.toExtensionId(namespaceName, extensionName); + throw new ErrorResultException(message, HttpStatus.NOT_FOUND); + } results.add(deleteExtension(user, extension)); } else { for (var targetVersion : targetVersions) { - var extVersion = repositories.findVersion(user, targetVersion.version(), targetVersion.targetPlatform(), extensionName, namespaceName); + var extVersion = repositories.findVersion( + user, + targetVersion.version(), + targetVersion.targetPlatform(), + extensionName, + namespaceName + ); if (extVersion == null) { var message = "Extension not found: " + NamingUtil.toLogFormat(namespaceName, extensionName, targetVersion.targetPlatform(), targetVersion.version()); throw new ErrorResultException(message, HttpStatus.NOT_FOUND); @@ -275,8 +288,7 @@ protected ResultJson deleteExtension(UserData user, Extension extension) throws cache.evictExtensionJsons(deprecatedExtension); } - entityManager.remove(extension); - search.removeSearchEntry(extension); + updateExtension(extension); var result = ResultJson.success("Deleted " + NamingUtil.toExtensionId(extension)); logs.logAction(user, result); @@ -286,7 +298,6 @@ protected ResultJson deleteExtension(UserData user, Extension extension) throws protected ResultJson deleteExtension(UserData user, ExtensionVersion extVersion) { var extension = extVersion.getExtension(); removeExtensionVersion(extVersion); - extension.getVersions().remove(extVersion); updateExtension(extension); var result = ResultJson.success("Deleted " + NamingUtil.toLogFormat(extVersion)); @@ -301,6 +312,6 @@ private void removeExtensionVersion(ExtensionVersion extVersion) { repositories.findFiles(extVersion).map(RemoveFileJobRequest::new).forEach(scheduler::enqueue); repositories.deleteFiles(extVersion); - entityManager.remove(extVersion); + extVersion.setState(ExtensionVersion.State.DELETED); } } \ No newline at end of file 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 6ca170c68..ef1ae55ae 100644 --- a/server/src/main/java/org/eclipse/openvsx/admin/AdminService.java +++ b/server/src/main/java/org/eclipse/openvsx/admin/AdminService.java @@ -164,8 +164,7 @@ public void deleteExtensionAndDependencies(Extension extension, UserData admin, cache.evictExtensionJsons(deprecatedExtension); } - entityManager.remove(extension); - search.removeSearchEntry(extension); + extensions.updateExtension(extension); logs.logAction(admin, ResultJson.success("Deleted " + NamingUtil.toExtensionId(extension))); } @@ -177,7 +176,6 @@ protected void deleteExtensionAndDependencies(ExtensionVersion extVersion, UserD } removeExtensionVersion(extVersion); - extension.getVersions().remove(extVersion); extensions.updateExtension(extension); logs.logAction(admin, ResultJson.success("Deleted " + NamingUtil.toLogFormat(extVersion))); } @@ -208,7 +206,7 @@ public ResultJson deleteExtension( public ResultJson deleteExtension(String namespaceName, String extensionName, UserData admin) throws ErrorResultException { var extension = repositories.findExtension(extensionName, namespaceName); - if (extension == null) { + if (extension == null || repositories.countVersions(namespaceName, extensionName) == 0) { var extensionId = NamingUtil.toExtensionId(namespaceName, extensionName); throw new ErrorResultException("Extension not found: " + extensionId, HttpStatus.NOT_FOUND); } @@ -259,8 +257,7 @@ protected ResultJson deleteExtension(Extension extension, UserData admin) throws cache.evictExtensionJsons(deprecatedExtension); } - entityManager.remove(extension); - search.removeSearchEntry(extension); + extensions.updateExtension(extension); var result = ResultJson.success("Deleted " + NamingUtil.toExtensionId(extension)); logs.logAction(admin, result); @@ -270,7 +267,6 @@ protected ResultJson deleteExtension(Extension extension, UserData admin) throws protected ResultJson deleteExtension(ExtensionVersion extVersion, UserData admin) { var extension = extVersion.getExtension(); removeExtensionVersion(extVersion); - extension.getVersions().remove(extVersion); extensions.updateExtension(extension); var result = ResultJson.success("Deleted " + NamingUtil.toLogFormat(extVersion)); @@ -323,7 +319,7 @@ private void removeExtensionVersion(ExtensionVersion extVersion) { repositories.findFiles(extVersion).map(RemoveFileJobRequest::new).forEach(scheduler::enqueue); repositories.deleteFiles(extVersion); - entityManager.remove(extVersion); + extVersion.setState(ExtensionVersion.State.DELETED); } private String userNotFoundMessage(String user) { 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 6814181d4..a5c23768e 100644 --- a/server/src/main/java/org/eclipse/openvsx/entities/ExtensionVersion.java +++ b/server/src/main/java/org/eclipse/openvsx/entities/ExtensionVersion.java @@ -79,6 +79,13 @@ public enum State { @ManyToOne private PersonalAccessToken publishedWith; + /** + * Legacy persisted mirror of {@link #state} kept for compatibility with active-based queries. + * + * @deprecated Use {@link #getState()} / {@link #setState(State)}. This field is planned for + * removal once repositories and SQL queries fully migrate to state-based filtering. + */ + @Deprecated(forRemoval = true) private boolean active; @Enumerated(EnumType.STRING) @@ -322,10 +329,18 @@ public void setPublishedWith(PersonalAccessToken publishedWith) { this.publishedWith = publishedWith; } + /** + * @deprecated Use {@code getState() == State.ACTIVE}. + */ + @Deprecated(forRemoval = true) public boolean isActive() { return state == State.ACTIVE; } + /** + * @deprecated Use {@link #setState(State)} with {@link State#ACTIVE} or {@link State#INACTIVE}. + */ + @Deprecated(forRemoval = true) public void setActive(boolean active) { setState(active ? State.ACTIVE : State.INACTIVE); } 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 14dd66e69..a9b559e84 100644 --- a/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionHandler.java +++ b/server/src/main/java/org/eclipse/openvsx/publish/PublishExtensionVersionHandler.java @@ -169,7 +169,7 @@ private ExtensionVersion createExtensionVersion(ExtensionProcessor processor, Us entityManager.persist(extension); } else { - var existingVersion = repositories.findVersion(extVersion.getVersion(), extVersion.getTargetPlatform(), extension); + var existingVersion = repositories.findVersionIncludingDeleted(extVersion.getVersion(), extVersion.getTargetPlatform(), extension); if (existingVersion != null) { var extVersionId = NamingUtil.toLogFormat(namespaceName, extensionName, extVersion.getTargetPlatform(), extVersion.getVersion()); var message = "Extension " + extVersionId + " is already published"; 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 b90d91136..ffe3e1708 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java @@ -477,19 +477,22 @@ private ExtensionVersion toExtensionVersionFull( newNamespace.setPublicId(row.get(NAMESPACE.PUBLIC_ID)); } - var user = new UserData(); - user.setId(row.get(USER_DATA.ID)); - user.setRole(row.get(USER_DATA.ROLE)); - user.setLoginName(row.get(USER_DATA.LOGIN_NAME)); - user.setFullName(row.get(USER_DATA.FULL_NAME)); - user.setAvatarUrl(row.get(USER_DATA.AVATAR_URL)); - user.setProviderUrl(row.get(USER_DATA.PROVIDER_URL)); - user.setProvider(row.get(USER_DATA.PROVIDER)); - - var token = new PersonalAccessToken(); - token.setUser(user); - - extVersion.setPublishedWith(token); + var userId = row.get(USER_DATA.ID); + if (userId != null) { + var user = new UserData(); + user.setId(userId); + user.setRole(row.get(USER_DATA.ROLE)); + user.setLoginName(row.get(USER_DATA.LOGIN_NAME)); + user.setFullName(row.get(USER_DATA.FULL_NAME)); + user.setAvatarUrl(row.get(USER_DATA.AVATAR_URL)); + user.setProviderUrl(row.get(USER_DATA.PROVIDER_URL)); + user.setProvider(row.get(USER_DATA.PROVIDER)); + + var token = new PersonalAccessToken(); + token.setUser(user); + extVersion.setPublishedWith(token); + } + extVersion.setType(ExtensionVersion.Type.REGULAR); return extVersion; } @@ -569,6 +572,7 @@ public List findTargetPlatformsGroupedByVersion(Exte ) .from(EXTENSION_VERSION) .where(EXTENSION_VERSION.EXTENSION_ID.eq(extension.getId())) + .and(EXTENSION_VERSION.STATE.ne(ExtensionVersion.State.DELETED.name())) .groupBy( EXTENSION_VERSION.SEMVER_MAJOR, EXTENSION_VERSION.SEMVER_MINOR, @@ -609,6 +613,7 @@ public List findTargetPlatformsGroupedByVersion(Exte .join(PERSONAL_ACCESS_TOKEN).on(PERSONAL_ACCESS_TOKEN.ID.eq(EXTENSION_VERSION.PUBLISHED_WITH_ID)) .where(EXTENSION_VERSION.EXTENSION_ID.eq(extension.getId())) .and(PERSONAL_ACCESS_TOKEN.USER_DATA.eq(user.getId())) + .and(EXTENSION_VERSION.STATE.ne(ExtensionVersion.State.DELETED.name())) .groupBy( EXTENSION_VERSION.SEMVER_MAJOR, EXTENSION_VERSION.SEMVER_MINOR, @@ -1481,6 +1486,19 @@ public Integer count(String namespaceName, String extensionName) { .fetchOne("count", Integer.class); } + public Integer countNonDeleted(String namespaceName, String extensionName) { + return dsl.select(DSL.count().as("count")) + .from(EXTENSION_VERSION) + .join(EXTENSION) + .on(EXTENSION.ID.eq(EXTENSION_VERSION.EXTENSION_ID)) + .join(NAMESPACE) + .on(NAMESPACE.ID.eq(EXTENSION.NAMESPACE_ID)) + .where(NAMESPACE.NAME.equalIgnoreCase(namespaceName)) + .and(EXTENSION.NAME.equalIgnoreCase(extensionName)) + .and(EXTENSION_VERSION.STATE.ne(ExtensionVersion.State.DELETED.name())) + .fetchOne("count", Integer.class); + } + public boolean isDeleteAllVersions(String namespaceName, String extensionName, List targetVersions, UserData user) { if(targetVersions.isEmpty()) { return false; @@ -1492,6 +1510,7 @@ public boolean isDeleteAllVersions(String namespaceName, String extensionName, L .join(NAMESPACE).on(NAMESPACE.ID.eq(EXTENSION.NAMESPACE_ID)) .and(NAMESPACE.NAME.equalIgnoreCase(namespaceName)) .and(EXTENSION.NAME.equalIgnoreCase(extensionName)) + .and(EXTENSION_VERSION.STATE.ne(ExtensionVersion.State.DELETED.name())) .fetchOne("all", Integer.class); var rows = targetVersions.stream().map((tv) -> DSL.row(tv.version(), tv.targetPlatform())).toArray(Row2[]::new); @@ -1507,6 +1526,7 @@ public boolean isDeleteAllVersions(String namespaceName, String extensionName, L .where(PERSONAL_ACCESS_TOKEN.USER_DATA.eq(user.getId())) .and(NAMESPACE.NAME.equalIgnoreCase(namespaceName)) .and(EXTENSION.NAME.equalIgnoreCase(extensionName)) + .and(EXTENSION_VERSION.STATE.ne(ExtensionVersion.State.DELETED.name())) .fetchOne("actual", Integer.class); return Objects.equals(actual, all); @@ -1515,10 +1535,10 @@ public boolean isDeleteAllVersions(String namespaceName, String extensionName, L public Page findChanges(LocalDateTime since, LocalDateTime before, int size, int offset) { var conditions = new ArrayList(); if (since != null) { - conditions.add(EXTENSION_VERSION.TIMESTAMP.greaterOrEqual(since)); + conditions.add(EXTENSION_VERSION.LAST_UPDATED.greaterOrEqual(since)); } if (before != null) { - conditions.add(EXTENSION_VERSION.TIMESTAMP.lessThan(before)); + conditions.add(EXTENSION_VERSION.LAST_UPDATED.lessThan(before)); } var countField = DSL.count(); @@ -1529,7 +1549,7 @@ public Page findChanges(LocalDateTime since, LocalDateTime bef var query = baseExtensionVersionQuery(); query.addConditions(conditions); - query.addOrderBy(EXTENSION_VERSION.TIMESTAMP.desc()); + query.addOrderBy(EXTENSION_VERSION.LAST_UPDATED.desc()); query.addLimit(size); query.addOffset(offset); diff --git a/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionRepository.java b/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionRepository.java index df07961f2..dfa9fd850 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionRepository.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionRepository.java @@ -27,10 +27,34 @@ public interface ExtensionVersionRepository extends Repository findByVersionAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(String version, String extensionName, String namespace); Streamable findByPublishedWithAndActive(PersonalAccessToken publishedWith, boolean active); @@ -41,11 +65,21 @@ public interface ExtensionVersionRepository extends Repository findBySignatureKeyPairNotOrSignatureKeyPairIsNull(SignatureKeyPair keyPair); - @Query("select ev from ExtensionVersion ev where concat(',', ev.bundledExtensions, ',') like concat('%,', ?1, ',%')") - Streamable findByBundledExtensions(String extensionId); - - @Query("select ev from ExtensionVersion ev where concat(',', ev.dependencies, ',') like concat('%,', ?1, ',%')") - Streamable findByDependencies(String extensionId); + @Query(""" + select ev + from ExtensionVersion ev + where concat(',', ev.bundledExtensions, ',') like concat('%,', ?1, ',%') + and ev.state <> ?2 + """) + Streamable findByBundledExtensionsAndStateNot(String extensionId, ExtensionVersion.State state); + + @Query(""" + select ev + from ExtensionVersion ev + where concat(',', ev.dependencies, ',') like concat('%,', ?1, ',%') + and ev.state <> ?2 + """) + Streamable findByDependenciesAndStateNot(String extensionId, ExtensionVersion.State state); @Query("select min(ev.timestamp) from ExtensionVersion ev") LocalDateTime getOldestTimestamp(); @@ -56,5 +90,18 @@ public interface ExtensionVersionRepository extends Repository findByExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(String extension, String namespace, Pageable page); + Page findByExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCaseAndActiveTrue( + String extension, + String namespace, + Pageable page + ); + Page findByTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(String targetPlatform, String extension, String namespace, Pageable page); + + Page findByTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCaseAndActiveTrue( + String targetPlatform, + String extension, + String namespace, + Pageable page + ); } \ No newline at end of file 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 b6b1e073d..25e3d7946 100644 --- a/server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java +++ b/server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java @@ -209,14 +209,44 @@ public int getMaxExtensionDownloadCount() { } public ExtensionVersion findVersion(String version, String targetPlatform, Extension extension) { + return extensionVersionRepo.findByVersionAndTargetPlatformAndExtensionAndStateNot( + version, + targetPlatform, + extension, + ExtensionVersion.State.DELETED + ); + } + + public ExtensionVersion findVersionIncludingDeleted(String version, String targetPlatform, Extension extension) { return extensionVersionRepo.findByVersionAndTargetPlatformAndExtension(version, targetPlatform, extension); } public ExtensionVersion findVersion(String version, String targetPlatform, String extensionName, String namespace) { + return extensionVersionRepo.findByVersionAndTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCaseAndStateNot( + version, + targetPlatform, + extensionName, + namespace, + ExtensionVersion.State.DELETED + ); + } + + public ExtensionVersion findVersionIncludingDeleted(String version, String targetPlatform, String extensionName, String namespace) { return extensionVersionRepo.findByVersionAndTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(version, targetPlatform, extensionName, namespace); } public ExtensionVersion findVersion(UserData user, String version, String targetPlatform, String extensionName, String namespace) { + return extensionVersionRepo.findByPublishedWithUserAndVersionAndTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCaseAndStateNot( + user, + version, + targetPlatform, + extensionName, + namespace, + ExtensionVersion.State.DELETED + ); + } + + public ExtensionVersion findVersionIncludingDeleted(UserData user, String version, String targetPlatform, String extensionName, String namespace) { return extensionVersionRepo.findByPublishedWithUserAndVersionAndTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(user, version, targetPlatform, extensionName, namespace); } @@ -229,11 +259,20 @@ public Streamable findActiveVersions(Extension extension) { } public Page findActiveVersionsSorted(String namespace, String extension, PageRequest page) { - return extensionVersionRepo.findByExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(extension, namespace, page.withSort(VERSIONS_SORT)); + return extensionVersionRepo.findByExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCaseAndActiveTrue( + extension, + namespace, + page.withSort(VERSIONS_SORT) + ); } public Page findActiveVersionsSorted(String namespace, String extension, String targetPlatform, PageRequest page) { - return extensionVersionRepo.findByTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCase(targetPlatform, extension, namespace, page.withSort(VERSIONS_SORT)); + return extensionVersionRepo.findByTargetPlatformAndExtensionNameIgnoreCaseAndExtensionNamespaceNameIgnoreCaseAndActiveTrue( + targetPlatform, + extension, + namespace, + page.withSort(VERSIONS_SORT) + ); } public Page findActiveVersionStringsSorted(String namespace, String extension, String targetPlatform, PageRequest page) { @@ -253,11 +292,17 @@ public List findActiveVersionReferencesSorted(Collection } public Streamable findBundledExtensionsReference(Extension extension) { - return extensionVersionRepo.findByBundledExtensions(NamingUtil.toExtensionId(extension)); + return extensionVersionRepo.findByBundledExtensionsAndStateNot( + NamingUtil.toExtensionId(extension), + ExtensionVersion.State.DELETED + ); } public Streamable findDependenciesReference(Extension extension) { - return extensionVersionRepo.findByDependencies(NamingUtil.toExtensionId(extension)); + return extensionVersionRepo.findByDependenciesAndStateNot( + NamingUtil.toExtensionId(extension), + ExtensionVersion.State.DELETED + ); } public Streamable findExtensions(UserData user) { @@ -513,6 +558,10 @@ public Streamable findTargetPlatformVersions(String version, S } public int countVersions(String namespaceName, String extensionName) { + return extensionVersionJooqRepo.countNonDeleted(namespaceName, extensionName); + } + + public int countAllVersions(String namespaceName, String extensionName) { return extensionVersionJooqRepo.count(namespaceName, extensionName); } diff --git a/server/src/main/java/org/eclipse/openvsx/scanning/ExtensionScanCompletionService.java b/server/src/main/java/org/eclipse/openvsx/scanning/ExtensionScanCompletionService.java index 738754c7d..f28b1dacf 100644 --- a/server/src/main/java/org/eclipse/openvsx/scanning/ExtensionScanCompletionService.java +++ b/server/src/main/java/org/eclipse/openvsx/scanning/ExtensionScanCompletionService.java @@ -685,6 +685,12 @@ public boolean adminAllowScan(ExtensionScan scan) { detachedVersion.getId(), scan.getId()); return false; } + + if (extVersion.getState() == ExtensionVersion.State.DELETED) { + logger.warn("Cannot activate deleted extension version for scan #{}: {}", + scan.getId(), NamingUtil.toLogFormat(extVersion)); + return false; + } // Already active - just mark scan passed if (extVersion.isActive()) { diff --git a/server/src/main/java/org/eclipse/openvsx/search/SimilarityCheckService.java b/server/src/main/java/org/eclipse/openvsx/search/SimilarityCheckService.java index 2fe021646..5453f5755 100644 --- a/server/src/main/java/org/eclipse/openvsx/search/SimilarityCheckService.java +++ b/server/src/main/java/org/eclipse/openvsx/search/SimilarityCheckService.java @@ -82,7 +82,7 @@ public PublishCheck.Result check(PublishCheck.Context context) { var extensionName = scan.getExtensionName(); var displayName = scan.getExtensionDisplayName(); - if (config.isOnlyCheckNewExtensions() && repositories.countVersions(namespaceName, extensionName) > 0) { + if (config.isOnlyCheckNewExtensions() && repositories.countAllVersions(namespaceName, extensionName) > 0) { return PublishCheck.Result.pass(); } diff --git a/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java b/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java index 0726f4578..b1d0307fd 100644 --- a/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java +++ b/server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java @@ -1700,6 +1700,17 @@ void testPublishExistingExtension() throws Exception { .andExpect(content().json(errorJson("Extension foo.bar 1.0.0 is already published."))); } + @Test + void testPublishDeletedExtensionVersion() throws Exception { + mockForPublish("existing-inactive"); + var bytes = createExtensionPackage("bar", "1.0.0", null); + mockMvc.perform(post("/api/-/publish?token={token}", "my_token") + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .content(bytes)) + .andExpect(status().isBadRequest()) + .andExpect(content().json(errorJson("Extension foo.bar 1.0.0 is already published, but currently isn't active and therefore not visible."))); + } + @Test void testPublishSameVersionDifferentTargetPlatformPreRelease() throws Exception { var extVersion = mockExtension(TargetPlatform.NAME_WIN32_X64); @@ -2502,16 +2513,20 @@ private void mockForPublish(String mode) { namespace.setName("foo"); Mockito.when(repositories.findNamespace("foo")) .thenReturn(namespace); - if (mode.equals("existing")) { + if (mode.equals("existing") || mode.equals("existing-inactive")) { var extension = new Extension(); extension.setName("bar"); var extVersion = new ExtensionVersion(); extVersion.setTargetPlatform(TargetPlatform.NAME_UNIVERSAL); extVersion.setVersion("1.0.0"); - extVersion.setActive(true); + if (mode.equals("existing-inactive")) { + extVersion.setState(ExtensionVersion.State.DELETED); + } else { + extVersion.setActive(true); + } Mockito.when(repositories.findExtension("bar", namespace)) .thenReturn(extension); - Mockito.when(repositories.findVersion("1.0.0", TargetPlatform.NAME_UNIVERSAL, extension)) + Mockito.when(repositories.findVersionIncludingDeleted("1.0.0", TargetPlatform.NAME_UNIVERSAL, extension)) .thenReturn(extVersion); } Mockito.when(repositories.countActiveReviews(any(Extension.class))) @@ -2536,7 +2551,7 @@ private void mockForPublish(String mode) { // Mock findMemberships(user) for similarity check Mockito.when(repositories.findMemberships(token.getUser())) .thenReturn(Streamable.of(ownerMem)); - } else if (mode.equals("contributor") || mode.equals("sole-contributor") || mode.equals("existing")) { + } else if (mode.equals("contributor") || mode.equals("sole-contributor") || mode.equals("existing") || mode.equals("existing-inactive")) { Mockito.when(repositories.canPublishInNamespace(token.getUser(), namespace)) .thenReturn(true); Mockito.when(repositories.isVerified(namespace, token.getUser())) diff --git a/server/src/test/java/org/eclipse/openvsx/UserAPITest.java b/server/src/test/java/org/eclipse/openvsx/UserAPITest.java index 8934cbb4f..bf1a59193 100644 --- a/server/src/test/java/org/eclipse/openvsx/UserAPITest.java +++ b/server/src/test/java/org/eclipse/openvsx/UserAPITest.java @@ -730,6 +730,8 @@ private List mockExtension(UserData user, int numberOfVersions extension.getVersions().addAll(versions); Mockito.when(repositories.findVersions(extension)) .thenReturn(Streamable.of(versions)); + Mockito.when(repositories.countVersions(namespace.getName(), extension.getName())) + .thenReturn(numberOfVersions); Mockito.when(repositories.findLatestVersions(user)).thenReturn(List.of(versions.get(versions.size() - 1))); Mockito.when(repositories.isDeleteAllVersions(eq("foobar"), eq("baz"), any(List.class), eq(user))).then(new Answer() { @Override 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 0c79034dd..cf0b1a17a 100644 --- a/server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java +++ b/server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java @@ -192,11 +192,15 @@ void testExecuteQueries() { () -> repositories.findUsersByLoginNameStartingWith("loginNameStart", 1), () -> repositories.findVersion("version", "targetPlatform", extension), () -> repositories.findVersion("version", "targetPlatform", "extensionName", "namespace"), + () -> repositories.findVersionIncludingDeleted("version", "targetPlatform", extension), () -> repositories.findVersions(extension), + () -> repositories.findVersionIncludingDeleted("version", "targetPlatform", "extensionName", "namespace"), () -> repositories.findVersionsByAccessToken(personalAccessToken, true), () -> repositories.getMaxExtensionDownloadCount(), () -> repositories.getOldestExtensionTimestamp(), + () -> repositories.countAllVersions("namespaceName", "extensionName"), () -> repositories.findExtensions(LONG_LIST), + () -> repositories.findVersionIncludingDeleted(userData, "version", "targetPlatform", "extensionName", "namespace"), () -> repositories.findExtensions(userData), () -> repositories.findFilesByType(List.of(extVersion), STRING_LIST), () -> repositories.countVersions("namespaceName", "extensionName"), diff --git a/server/src/test/java/org/eclipse/openvsx/search/SimilarityCheckServiceTest.java b/server/src/test/java/org/eclipse/openvsx/search/SimilarityCheckServiceTest.java index 863c2c207..27fc4b70a 100644 --- a/server/src/test/java/org/eclipse/openvsx/search/SimilarityCheckServiceTest.java +++ b/server/src/test/java/org/eclipse/openvsx/search/SimilarityCheckServiceTest.java @@ -148,13 +148,13 @@ void shouldDelegateSimilarExtensionsToService() { void shouldSkipCheckForExistingExtensionWhenConfiguredForNewOnly() { // When configured for new extensions only, skip if extension already has versions (>1 means existing). when(config.isOnlyCheckNewExtensions()).thenReturn(true); - when(repositories.countVersions("ns", "ext")).thenReturn(2); + when(repositories.countAllVersions("ns", "ext")).thenReturn(2); var context = createContext("ns", "ext", "Display"); var result = similarityCheckService.check(context); assertThat(result.passed()).isTrue(); - verify(repositories).countVersions("ns", "ext"); + verify(repositories).countAllVersions("ns", "ext"); verifyNoInteractions(similarityService); } @@ -165,7 +165,7 @@ void shouldCheckNewExtensionEvenWhenConfiguredForNewOnly() { when(config.isAllowSimilarityToOwnNames()).thenReturn(false); when(config.getSimilarityThreshold()).thenReturn(0.15); when(config.isOnlyProtectVerifiedNames()).thenReturn(false); - when(repositories.countVersions("ns", "ext")).thenReturn(0); + when(repositories.countAllVersions("ns", "ext")).thenReturn(0); when(similarityService.findSimilarExtensions("ext", "ns", "Display", List.of(), 0.15, false, 10)) .thenReturn(List.of()); @@ -173,7 +173,7 @@ void shouldCheckNewExtensionEvenWhenConfiguredForNewOnly() { var result = similarityCheckService.check(context); assertThat(result.passed()).isTrue(); - verify(repositories).countVersions("ns", "ext"); + verify(repositories).countAllVersions("ns", "ext"); verify(similarityService).findSimilarExtensions("ext", "ns", "Display", List.of(), 0.15, false, 10); }