Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ dependencies {
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.13.0'
implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.13.0'
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.13.0'
implementation group: 'io.searchbox', name: 'jest', version: '6.3.1'
implementation group: 'io.vavr', name: 'vavr', version: '0.11.0'
implementation group: 'jakarta.validation', name: 'jakarta.validation-api', version: '3.1.1'
implementation group: 'org.apache.commons', name: 'commons-jexl3', version: '3.6.1'
Expand Down
2 changes: 0 additions & 2 deletions src/contractTest/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ search.cases.index.name.type=${ELASTIC_SEARCH_CASE_INDEX_TYPE:_doc}
search.elastic.nodes.discovery.enabled=${ELASTIC_SEARCH_NODES_DISCOVERY_ENABLED:false}
search.elastic.nodes.discovery.frequency.millis=${ELASTIC_SEARCH_NODES_DISCOVERY_FREQUENCY_MILLIS:5000}
search.elastic.nodes.discovery.filter=${ELASTIC_SEARCH_NODES_DISCOVERY_FILTER:_all}
spring.elasticsearch.jest.uris=${ELASTIC_SEARCH_HOSTS:http://localhost:9200}
spring.elasticsearch.jest.read-timeout=10000ms
search.global.index.name=${GLOBAL_SEARCH_INDEX_NAME:global_search}
search.global.index.type=${GLOBAL_SEARCH_INDEX_TYPE:_doc}
search.internal.case-access-metadata.enabled=${INTERNAL_SEARCH_CAM_ENABLED:false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import co.elastic.clients.elasticsearch.core.MsearchRequest;
import co.elastic.clients.elasticsearch.core.MsearchResponse;
import co.elastic.clients.elasticsearch.core.msearch.MultiSearchResponseItem;
import co.elastic.clients.elasticsearch.core.msearch.RequestItem;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.searchbox.core.Search;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
Expand All @@ -32,7 +32,6 @@
import java.util.stream.Collectors;

import static java.lang.String.format;
import static java.util.stream.Collectors.toList;

@Service
@Qualifier(ElasticsearchCaseSearchOperation.QUALIFIER)
Expand Down Expand Up @@ -80,38 +79,38 @@ private MsearchResponse<ElasticSearchCaseDetailsDTO> search(CrossCaseTypeSearchR
}

private MsearchRequest secureAndTransformSearchRequest(CrossCaseTypeSearchRequest request) {
final List<Search> securedSearches = request.getSearchIndex()
.map(searchIndex -> List.of(createSecuredSearch(searchIndex, request)))
.orElseGet(() -> buildSearchesByCaseType(request));
return JestToESConverter.fromJest(securedSearches);
final List<RequestItem> securedSearches = request.getSearchIndex()
.map(searchIndex -> List.of(createSecuredRequestItem(searchIndex, request)))
.orElseGet(() -> buildRequestItemsByCaseType(request));
return new MsearchRequest.Builder().searches(securedSearches).build();
}

private List<Search> buildSearchesByCaseType(final CrossCaseTypeSearchRequest request) {
private List<RequestItem> buildRequestItemsByCaseType(final CrossCaseTypeSearchRequest request) {
return request.getCaseTypeIds()
.stream()
.map(caseTypeId -> createSecuredSearch(caseTypeId, request))
.collect(toList());
.map(caseTypeId -> createSecuredRequestItem(caseTypeId, request))
.toList();
}

private Search createSecuredSearch(final SearchIndex searchIndex, final CrossCaseTypeSearchRequest request) {
private RequestItem createSecuredRequestItem(final SearchIndex searchIndex,
final CrossCaseTypeSearchRequest request) {
final CrossCaseTypeSearchRequest securedSearchRequest =
caseSearchRequestSecurity.createSecuredSearchRequest(request);

final ElasticsearchRequest elasticSearchRequest = securedSearchRequest.getElasticSearchRequest();

return new Search.Builder(elasticSearchRequest.toFinalRequest())
.addIndex(searchIndex.getIndexName())
.addType(searchIndex.getIndexType())
.build();
return ElasticsearchMsearchRequestBuilder.createRequestItem(
searchIndex.getIndexName(),
elasticSearchRequest.toFinalRequest()
);
}

private Search createSecuredSearch(String caseTypeId, CrossCaseTypeSearchRequest request) {
private RequestItem createSecuredRequestItem(String caseTypeId, CrossCaseTypeSearchRequest request) {
CaseSearchRequest securedSearchRequest = caseSearchRequestSecurity.createSecuredSearchRequest(
new CaseSearchRequest(caseTypeId, request.getElasticSearchRequest()));
return new Search.Builder(securedSearchRequest.toJsonString())
.addIndex(getCaseIndexName(caseTypeId))
.addType(getCaseIndexType())
.build();
return ElasticsearchMsearchRequestBuilder.createRequestItem(
getCaseIndexName(caseTypeId),
securedSearchRequest.toJsonString()
);
}

private CaseSearchResult toCaseDetailsSearchResult(MsearchResponse<ElasticSearchCaseDetailsDTO> multiSearchResult,
Expand Down Expand Up @@ -189,8 +188,4 @@ private String getCaseIndexName(String caseTypeId) {
return format(applicationParams.getCasesIndexNameFormat(), caseTypeId.toLowerCase());
}

private String getCaseIndexType() {
return applicationParams.getCasesIndexType();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package uk.gov.hmcts.ccd.domain.service.search.elasticsearch;

import co.elastic.clients.elasticsearch.core.msearch.RequestItem;
import co.elastic.clients.elasticsearch.core.search.SearchRequestBody;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;

import java.io.StringReader;

public final class ElasticsearchMsearchRequestBuilder {

private static final String INCLUDES = "includes";
private static final JsonpMapper MAPPER = new JacksonJsonpMapper();
private static final String SOURCE = "_source";

private ElasticsearchMsearchRequestBuilder() {
}

public static RequestItem createRequestItem(String indexName, String bodyJson) {
if (bodyJson == null || bodyJson.isBlank()) {
throw new IllegalArgumentException("Search request body is empty");
}

SearchRequestBody body = parseBody(bodyJson);
return new RequestItem.Builder()
.header(h -> {
if (indexName != null && !indexName.isBlank()) {
h.index(indexName);
}
return h;
})
.body(body)
.build();
}

private static SearchRequestBody parseBody(String json) {
String normalizedBody = normalizeSourceSyntax(json);
try {
return SearchRequestBody._DESERIALIZER.deserialize(
MAPPER.jsonProvider().createParser(new StringReader(normalizedBody)),
MAPPER
);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to parse search request body", e);
}
}

private static String normalizeSourceSyntax(String json) {
try (JsonReader reader = Json.createReader(new StringReader(json))) {
JsonObject body = reader.readObject();
if (!body.containsKey(SOURCE)) {
return json;
}

JsonValue source = body.get(SOURCE);
if (source.getValueType() != JsonValue.ValueType.ARRAY) {
return json;
}

JsonArray sourceIncludes = source.asJsonArray();
JsonObject normalizedSource = Json.createObjectBuilder()
.add(INCLUDES, sourceIncludes)
.build();

JsonObjectBuilder normalizedBody = Json.createObjectBuilder();
body.forEach((key, value) -> {
if (SOURCE.equals(key)) {
normalizedBody.add(key, normalizedSource);
} else {
normalizedBody.add(key, value);
}
});

return normalizedBody.build().toString();
}
}
}

This file was deleted.

This file was deleted.

2 changes: 0 additions & 2 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@ search.cases.index.name.type=${ELASTIC_SEARCH_CASE_INDEX_TYPE:_doc}
search.elastic.nodes.discovery.enabled=${ELASTIC_SEARCH_NODES_DISCOVERY_ENABLED:false}
search.elastic.nodes.discovery.frequency.millis=${ELASTIC_SEARCH_NODES_DISCOVERY_FREQUENCY_MILLIS:5000}
search.elastic.nodes.discovery.filter=${ELASTIC_SEARCH_NODES_DISCOVERY_FILTER:_all}
spring.elasticsearch.jest.uris=${ELASTIC_SEARCH_HOSTS:http://localhost:9200}
spring.elasticsearch.jest.read-timeout=10000ms
search.global.index.name=${GLOBAL_SEARCH_INDEX_NAME:global_search}
search.global.index.type=${GLOBAL_SEARCH_INDEX_TYPE:_doc}
search.internal.case-access-metadata.enabled=${INTERNAL_SEARCH_CAM_ENABLED:false}
Expand Down
Loading