diff --git a/src/main/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpoint.java b/src/main/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpoint.java index 2d0597b22..57e2bd553 100644 --- a/src/main/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpoint.java +++ b/src/main/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpoint.java @@ -4,6 +4,7 @@ import static java.util.Comparator.comparing; import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder; import static org.springdoc.core.fn.builders.content.Builder.contentBuilder; import static org.springdoc.core.fn.builders.schema.Builder.schemaBuilder; +import static org.springframework.boot.convert.ApplicationConversionService.getSharedInstance; import static org.springframework.web.reactive.function.BodyExtractors.toMultipartData; import static org.springframework.web.reactive.function.server.RequestPredicates.contentType; import static run.halo.app.extension.ListResult.generateGenericClass; @@ -168,6 +169,10 @@ public class AttachmentEndpoint implements CustomEndpoint { @Schema(description = "Name of group") Optional getGroup(); + @Schema(description = "Filter attachments without group. This parameter will ignore group" + + " parameter.") + Optional getUngrouped(); + @Schema(description = "Name of user who uploaded the attachment") Optional getUploadedBy(); @@ -209,6 +214,12 @@ public class AttachmentEndpoint implements CustomEndpoint { .filter(StringUtils::hasText); } + @Override + public Optional getUngrouped() { + return Optional.ofNullable(queryParams.getFirst("ungrouped")) + .map(ungroupedStr -> getSharedInstance().convert(ungroupedStr, Boolean.class)); + } + @Override public Optional getUploadedBy() { return Optional.ofNullable(queryParams.getFirst("uploadedBy")) @@ -221,33 +232,49 @@ public class AttachmentEndpoint implements CustomEndpoint { } public Predicate toPredicate() { - var predicate = (Predicate) (attachment) -> getDisplayName() + Predicate displayNamePred = attachment -> getDisplayName() .map(displayNameInParam -> { String displayName = attachment.getSpec().getDisplayName(); return displayName.contains(displayNameInParam); - }).orElse(true) - && getPolicy() + }).orElse(true); + + Predicate policyPred = attachment -> getPolicy() .map(policy -> { var policyRef = attachment.getSpec().getPolicyRef(); return policyRef != null && policy.equals(policyRef.getName()); - }).orElse(true) - && getGroup() + }).orElse(true); + + Predicate groupPred = attachment -> getGroup() .map(group -> { var groupRef = attachment.getSpec().getGroupRef(); return groupRef != null && group.equals(groupRef.getName()); }) - .orElse(true) - && getUploadedBy() + .orElse(true); + + Predicate ungroupedPred = attachment -> getUngrouped() + .filter(Boolean::booleanValue) + .map(ungrouped -> { + var groupRef = attachment.getSpec().getGroupRef(); + return groupRef == null || !StringUtils.hasText(groupRef.getName()); + }) + .orElseGet(() -> groupPred.test(attachment)); + + Predicate uploadedByPred = attachment -> getUploadedBy() .map(uploadedBy -> { var uploadedByRef = attachment.getSpec().getUploadedBy(); return uploadedByRef != null && uploadedBy.equals(uploadedByRef.getName()); }) .orElse(true); - var selectorPredicate = labelAndFieldSelectorToPredicate(getLabelSelector(), - getFieldSelector()); - return predicate.and(selectorPredicate); + var selectorPred = + labelAndFieldSelectorToPredicate(getLabelSelector(), getFieldSelector()); + + return displayNamePred + .and(policyPred) + .and(ungroupedPred) + .and(uploadedByPred) + .and(selectorPred); } public Comparator toComparator() { diff --git a/src/test/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpointTest.java b/src/test/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpointTest.java index 82b90fee4..6af1436e1 100644 --- a/src/test/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpointTest.java +++ b/src/test/java/run/halo/app/core/extension/attachment/endpoint/AttachmentEndpointTest.java @@ -1,6 +1,10 @@ package run.halo.app.core.extension.attachment.endpoint; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -18,13 +22,19 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.MediaType; import org.springframework.http.client.MultipartBodyBuilder; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.reactive.function.server.MockServerRequest; +import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.reactive.function.BodyInserters; import reactor.core.publisher.Mono; import run.halo.app.core.extension.attachment.Attachment; +import run.halo.app.core.extension.attachment.Attachment.AttachmentSpec; import run.halo.app.core.extension.attachment.Policy; import run.halo.app.core.extension.attachment.Policy.PolicySpec; +import run.halo.app.core.extension.attachment.endpoint.AttachmentEndpoint.SearchRequest; import run.halo.app.extension.ConfigMap; +import run.halo.app.extension.ListResult; import run.halo.app.extension.Metadata; import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.Ref; @@ -149,4 +159,45 @@ class AttachmentEndpointTest { } } + @Nested + class SearchTest { + + @Test + void shouldListUngroupedAttachments() { + when(client.list(same(Attachment.class), any(), any(), anyInt(), anyInt())) + .thenReturn(Mono.just(ListResult.emptyResult())); + + webClient + .get() + .uri("/attachments") + .exchange() + .expectStatus().isOk() + .expectBody() + .jsonPath("items.length()").isEqualTo(0); + } + + @Test + void shouldFilterWithUngrouped() { + var httpRequest = MockServerHttpRequest.get("/attachments") + .build(); + var exchange = new MockServerWebExchange.Builder(httpRequest) + .build(); + MockServerRequest request = MockServerRequest.builder() + .queryParam("ungrouped", "true") + .queryParam("group", "halo") + .exchange(exchange) + .build(); + var searchRequest = new SearchRequest(request); + var pred = searchRequest.toPredicate(); + var attachment = new Attachment(); + var spec = new AttachmentSpec(); + attachment.setSpec(spec); + + assertTrue(pred.test(attachment)); + + spec.setGroupRef(Ref.of("halo")); + assertFalse(pred.test(attachment)); + } + } + } \ No newline at end of file