mirror of https://github.com/halo-dev/halo
Provide ungrouped query param to filter ungrouped attachments (#2752)
#### What type of PR is this? /kind feature /area core /milestone 2.0.0-rc.1 #### What this PR does / why we need it: Provide `ungrouped` query param to filter ungrouped attachments. Please note that we will ignore `group` query param when `ungropued` is `true`. ```bash curl -X 'GET' \ 'http://localhost:8090/apis/api.console.halo.run/v1alpha1/attachments?ungrouped=true' \ -H 'accept: */*' ``` #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2451 #### Does this PR introduce a user-facing change? ```release-note None ```pull/2760/head
parent
b0c461b5f6
commit
f96ef7f1b3
|
@ -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.apiresponse.Builder.responseBuilder;
|
||||||
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
|
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
|
||||||
import static org.springdoc.core.fn.builders.schema.Builder.schemaBuilder;
|
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.BodyExtractors.toMultipartData;
|
||||||
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
|
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
|
||||||
import static run.halo.app.extension.ListResult.generateGenericClass;
|
import static run.halo.app.extension.ListResult.generateGenericClass;
|
||||||
|
@ -168,6 +169,10 @@ public class AttachmentEndpoint implements CustomEndpoint {
|
||||||
@Schema(description = "Name of group")
|
@Schema(description = "Name of group")
|
||||||
Optional<String> getGroup();
|
Optional<String> getGroup();
|
||||||
|
|
||||||
|
@Schema(description = "Filter attachments without group. This parameter will ignore group"
|
||||||
|
+ " parameter.")
|
||||||
|
Optional<Boolean> getUngrouped();
|
||||||
|
|
||||||
@Schema(description = "Name of user who uploaded the attachment")
|
@Schema(description = "Name of user who uploaded the attachment")
|
||||||
Optional<String> getUploadedBy();
|
Optional<String> getUploadedBy();
|
||||||
|
|
||||||
|
@ -209,6 +214,12 @@ public class AttachmentEndpoint implements CustomEndpoint {
|
||||||
.filter(StringUtils::hasText);
|
.filter(StringUtils::hasText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Boolean> getUngrouped() {
|
||||||
|
return Optional.ofNullable(queryParams.getFirst("ungrouped"))
|
||||||
|
.map(ungroupedStr -> getSharedInstance().convert(ungroupedStr, Boolean.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> getUploadedBy() {
|
public Optional<String> getUploadedBy() {
|
||||||
return Optional.ofNullable(queryParams.getFirst("uploadedBy"))
|
return Optional.ofNullable(queryParams.getFirst("uploadedBy"))
|
||||||
|
@ -221,33 +232,49 @@ public class AttachmentEndpoint implements CustomEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Predicate<Attachment> toPredicate() {
|
public Predicate<Attachment> toPredicate() {
|
||||||
var predicate = (Predicate<Attachment>) (attachment) -> getDisplayName()
|
Predicate<Attachment> displayNamePred = attachment -> getDisplayName()
|
||||||
.map(displayNameInParam -> {
|
.map(displayNameInParam -> {
|
||||||
String displayName = attachment.getSpec().getDisplayName();
|
String displayName = attachment.getSpec().getDisplayName();
|
||||||
return displayName.contains(displayNameInParam);
|
return displayName.contains(displayNameInParam);
|
||||||
}).orElse(true)
|
}).orElse(true);
|
||||||
&& getPolicy()
|
|
||||||
|
Predicate<Attachment> policyPred = attachment -> getPolicy()
|
||||||
.map(policy -> {
|
.map(policy -> {
|
||||||
var policyRef = attachment.getSpec().getPolicyRef();
|
var policyRef = attachment.getSpec().getPolicyRef();
|
||||||
return policyRef != null && policy.equals(policyRef.getName());
|
return policyRef != null && policy.equals(policyRef.getName());
|
||||||
}).orElse(true)
|
}).orElse(true);
|
||||||
&& getGroup()
|
|
||||||
|
Predicate<Attachment> groupPred = attachment -> getGroup()
|
||||||
.map(group -> {
|
.map(group -> {
|
||||||
var groupRef = attachment.getSpec().getGroupRef();
|
var groupRef = attachment.getSpec().getGroupRef();
|
||||||
return groupRef != null && group.equals(groupRef.getName());
|
return groupRef != null && group.equals(groupRef.getName());
|
||||||
})
|
})
|
||||||
.orElse(true)
|
.orElse(true);
|
||||||
&& getUploadedBy()
|
|
||||||
|
Predicate<Attachment> 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<Attachment> uploadedByPred = attachment -> getUploadedBy()
|
||||||
.map(uploadedBy -> {
|
.map(uploadedBy -> {
|
||||||
var uploadedByRef = attachment.getSpec().getUploadedBy();
|
var uploadedByRef = attachment.getSpec().getUploadedBy();
|
||||||
return uploadedByRef != null && uploadedBy.equals(uploadedByRef.getName());
|
return uploadedByRef != null && uploadedBy.equals(uploadedByRef.getName());
|
||||||
})
|
})
|
||||||
.orElse(true);
|
.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<Attachment> toComparator() {
|
public Comparator<Attachment> toComparator() {
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package run.halo.app.core.extension.attachment.endpoint;
|
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.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.same;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -18,13 +22,19 @@ import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.client.MultipartBodyBuilder;
|
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.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.web.reactive.function.BodyInserters;
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import run.halo.app.core.extension.attachment.Attachment;
|
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;
|
||||||
import run.halo.app.core.extension.attachment.Policy.PolicySpec;
|
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.ConfigMap;
|
||||||
|
import run.halo.app.extension.ListResult;
|
||||||
import run.halo.app.extension.Metadata;
|
import run.halo.app.extension.Metadata;
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.extension.Ref;
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue