fix(search): require published portal results

Signed-off-by: dongmucat <1127093059@qq.com>
This commit is contained in:
dongmucat 2026-07-28 10:57:52 +08:00
parent 1d216e73f0
commit e066277065
2 changed files with 38 additions and 5 deletions

View file

@ -107,9 +107,7 @@ public class PostgresFullTextQueryService implements SearchQueryService {
sql.append("FROM skill_search_document d ");
sql.append("JOIN skill s ON s.id = d.skill_id ");
sql.append("JOIN namespace n ON n.id = d.namespace_id ");
if (query.requireInstallableLatest()) {
sql.append("JOIN skill_version latest ON latest.id = s.latest_version_id ");
}
sql.append("JOIN skill_version latest ON latest.id = s.latest_version_id ");
sql.append("WHERE 1=1 ");
// Visibility filtering
@ -123,10 +121,10 @@ public class PostgresFullTextQueryService implements SearchQueryService {
sql.append("AND d.status = 'ACTIVE' ");
sql.append("AND s.status = 'ACTIVE' ");
sql.append("AND s.hidden = FALSE ");
sql.append("AND latest.status = 'PUBLISHED' ");
sql.append("AND latest.yanked_at IS NULL ");
if (query.requireInstallableLatest()) {
sql.append("AND latest.status = 'PUBLISHED' ");
sql.append("AND latest.download_ready = TRUE ");
sql.append("AND latest.yanked_at IS NULL ");
}
sql.append("AND (n.status <> 'ARCHIVED' ");
if (query.visibilityScope().userId() != null) {

View file

@ -400,6 +400,41 @@ class PostgresFullTextQueryServiceTest {
verify(countQuery, never()).setParameter(org.mockito.ArgumentMatchers.eq("memberNamespaceIds"), org.mockito.ArgumentMatchers.any());
}
@Test
void portalSearchShouldRequirePublishedNonYankedLatestWithoutDownloadReadiness() {
EntityManager entityManager = mock(EntityManager.class);
Query nativeQuery = mock(Query.class);
Query countQuery = mock(Query.class);
when(entityManager.createNativeQuery(anyString()))
.thenReturn(nativeQuery)
.thenReturn(countQuery);
when(nativeQuery.setParameter(anyString(), org.mockito.ArgumentMatchers.any())).thenReturn(nativeQuery);
when(countQuery.setParameter(anyString(), org.mockito.ArgumentMatchers.any())).thenReturn(countQuery);
when(nativeQuery.getResultList()).thenReturn(List.of());
when(countQuery.getSingleResult()).thenReturn(0L);
PostgresFullTextQueryService service = new PostgresFullTextQueryService(entityManager);
service.search(new SearchQuery(
"demo",
null,
SearchVisibilityScope.anonymous(),
"newest",
0,
12,
List.of(),
false
));
ArgumentCaptor<String> sqlCaptor = ArgumentCaptor.forClass(String.class);
verify(entityManager, org.mockito.Mockito.times(2)).createNativeQuery(sqlCaptor.capture());
assertThat(sqlCaptor.getAllValues()).allSatisfy(sql -> assertThat(sql)
.contains("JOIN skill_version latest ON latest.id = s.latest_version_id")
.contains("AND latest.status = 'PUBLISHED'")
.contains("AND latest.yanked_at IS NULL")
.doesNotContain("latest.download_ready = TRUE"));
}
@Test
void installableLatestFilterShouldApplyToSearchAndCountQueries() {
EntityManager entityManager = mock(EntityManager.class);