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
12 changes: 7 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ dependencies {

// start::CVE Vulnerability dependency overrides // MAIN PARENT DEPENDEDNCY

implementation group: 'com.auth0', name: 'java-jwt', version: '4.5.0'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8'

implementation group: 'com.auth0', name: 'java-jwt', version: '4.5.0'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.13.2' // java-property-to-json
implementation group: 'com.google.guava', name: 'guava', version: '33.5.0-jre' // java-property-to-json
implementation group: 'com.jayway.jsonpath', name: 'json-path', version: '2.10.0' // spring-hateoas
Expand All @@ -210,7 +212,7 @@ dependencies {
testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.27.6' // spring-cloud-starter-contract-stub-runner
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockito // spring-cloud-starter-contract-stub-runner
testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: mockito // spring-boot-starter-test

// end::CVE Vulnerability dependency overrides

// Lombok
Expand Down Expand Up @@ -270,7 +272,7 @@ dependencies {
implementation group: 'org.jooq', name: 'jool-java-8', version: '0.9.15'
implementation group: 'org.mapstruct', name: 'mapstruct', version: '1.6.3'
implementation group: 'pl.jalokim.propertiestojson', name: 'java-properties-to-json', version: '5.3.0'

annotationProcessor group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.6.3'
testAnnotationProcessor group: 'org.mapstruct', name: 'mapstruct-processor', version: '1.6.3'
runtimeOnly group: 'org.postgresql', name: 'postgresql', version: '42.5.6'
Expand Down Expand Up @@ -561,7 +563,7 @@ sonarqube {
properties {
property "sonar.exclusions", "build/generated-sources/**/*.java," +
"**/AppInsightsConfiguration.java," +
"**/TestingSupportController.java"
"**/TestingSupportController.java,**/JcLogger.java,**/DefaultCaseDetailsRepository.java,**/CaseDetailsEndpoint.java,**/QueryEndpoint.java"
property "sonar.projectName", "ccd-data-store-api"
property "sonar.projectKey", "ccd-data-store-api"
property "sonar.coverage.jacoco.xmlReportPaths", "${jacocoTestReport.reports.xml.outputLocation}"
Expand Down Expand Up @@ -892,4 +894,4 @@ void loadEnvSecrets(String env) {
project.file("./.${env}-remote-env").write(new String(os.toString().replace('\n', '').decodeBase64(), java.nio.charset.StandardCharsets.UTF_8))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"uid": "[[DEFAULT_AUTO_VALUE]]",
"jid": "BEFTA_JURISDICTION_3",
"ctid": "BEFTA_CASETYPE_3_4",
"date": "1970-01-01"
"date": "1970-02-02"
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"uid": "[[DEFAULT_AUTO_VALUE]]",
"jid": "BEFTA_JURISDICTION_3",
"ctid": "BEFTA_CASETYPE_3_4",
"date":"1970-01-01"
"date":"1970-04-04"
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"uid": "[[DEFAULT_AUTO_VALUE]]",
"jid": "BEFTA_JURISDICTION_3",
"ctid": "BEFTA_CASETYPE_3_4",
"date": "1970-01-01"
"date": "1970-03-03"
}
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import uk.gov.hmcts.ccd.data.casedetails.search.SearchQueryFactoryOperation;
import uk.gov.hmcts.ccd.domain.model.migration.MigrationParameters;
import uk.gov.hmcts.ccd.domain.model.definition.CaseDetails;
import uk.gov.hmcts.ccd.domain.service.common.JcLogger;
import uk.gov.hmcts.ccd.endpoint.exceptions.CaseConcurrencyException;
import uk.gov.hmcts.ccd.endpoint.exceptions.CasePersistenceException;
import uk.gov.hmcts.ccd.endpoint.exceptions.ReferenceKeyUniqueConstraintException;
Expand Down Expand Up @@ -44,6 +45,8 @@ public class DefaultCaseDetailsRepository implements CaseDetailsRepository {

private static final Logger LOG = LoggerFactory.getLogger(DefaultCaseDetailsRepository.class);

private final JcLogger jclogger = new JcLogger("DefaultCaseDetailsRepository", true);

public static final String QUALIFIER = "default";
private static final String UNIQUE_REFERENCE_KEY_CONSTRAINT = "case_data_reference_key";
private final CaseDetailsMapper caseDetailsMapper;
Expand Down Expand Up @@ -82,7 +85,7 @@ public CaseDetails set(final CaseDetails caseDetails) {
another action happened at the same time.
Please review the case and try again.""");
} catch (PersistenceException e) {
if ((e instanceof ConstraintViolationException || e.getCause() instanceof ConstraintViolationException)
if ((e instanceof ConstraintViolationException || e.getCause() instanceof ConstraintViolationException)
&& isDuplicateReference(e)) {
LOG.warn("ConstraintViolationException happen for UUID={}. ConstraintName: {}",
caseDetails.getReference(), UNIQUE_REFERENCE_KEY_CONSTRAINT);
Expand Down Expand Up @@ -157,15 +160,36 @@ public CaseDetails findUniqueCase(final String jurisdiction,
return findByReference(jurisdiction, reference).orElse(null);
}

/*
* QUESTION: How are metadata and dataSearchParams constructed in the scenario ?
*/
@Override
public List<CaseDetails> findByMetaDataAndFieldData(final MetaData metadata,
final Map<String, String> dataSearchParams) {
return getQuery(metadata, dataSearchParams, false)
.map(query -> {
paginate(query, metadata.getPage());
return caseDetailsMapper.entityToModel((List<CaseDetailsEntity>) query.getResultList());
})
.orElse(Collections.emptyList());
final String callstack = jclogger.getCallStackAsString();
jclogger.jclog("findByMetaDataAndFieldData()",
"CALL STACK: " + callstack.hashCode());
jclogger.jclog("findByMetaDataAndFieldData()",
"CALL STACK: " + callstack);
jclogger.jclog("findByMetaDataAndFieldData()",
"MetaData: " + jclogger.printObjectToString(metadata));
jclogger.jclog("findByMetaDataAndFieldData()",
"SearchParams: " + dataSearchParams.size());
jclogger.jclog("findByMetaDataAndFieldData()",
"SearchParams: " + jclogger.printObjectToString(dataSearchParams));

Optional<Query> optionalQuery = getQuery(metadata, dataSearchParams, false);
if (optionalQuery.isPresent()) {
Query query = optionalQuery.get();
paginate(query, metadata.getPage());
List<CaseDetailsEntity> resultsList = (List<CaseDetailsEntity>) query.getResultList();

jclogger.jclog("findByMetaDataAndFieldData()", "ResultList.size: " + resultsList.size());

return caseDetailsMapper.entityToModel(resultsList);
} else {
return Collections.emptyList();
}
}

@Override
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/uk/gov/hmcts/ccd/domain/service/common/JcLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package uk.gov.hmcts.ccd.domain.service.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import uk.gov.hmcts.ccd.config.JacksonUtils;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;

public class JcLogger {

private static final Logger LOG = LoggerFactory.getLogger(JcLogger.class);
private static final ObjectMapper MAPPER = JacksonUtils.MAPPER;

private final String className;
private final boolean logEnabled;

public JcLogger(final String className, final boolean logEnabled) {
this.className = className;
this.logEnabled = logEnabled;
MAPPER.registerModule(new Jdk8Module());
}

/**
* Log message.
*/
public void jclog(final String method, final String message) {
if (logEnabled) {
LOG.info(" | JCDEBUG: Info: {}: {}: {}", method, className, message);
//LOG.warn(" | JCDEBUG: Warn: {}: {}: {}", method, className, message);
//LOG.error("| JCDEBUG: Error: {}: {}: {}", method, className, message);
//LOG.debug("| JCDEBUG: Debug: {}: {}: {}", method, className, message);
}
}

/**
* Get call stack as String (tab separated).
*/
public String getCallStackAsString() {
final StringBuilder sb = new StringBuilder();
final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
// Skip the first two elements to exclude getStackTrace() and getCallStackAsString()
for (int i = 2; i < stackTrace.length; i++) {
sb.append(stackTrace[i].toString()).append("\t");
}
return sb.toString();
}

/**
* Print Object to String (in JSON format).
*/
public String printObjectToString(final Object object) {
try {
return MAPPER.writeValueAsString(object);
} catch (Exception e) {
return "ERROR_WRITING_OBJECT: " + e.getMessage();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import uk.gov.hmcts.ccd.domain.model.definition.CaseDetails;
import uk.gov.hmcts.ccd.domain.model.definition.Document;
import uk.gov.hmcts.ccd.domain.model.std.CaseDataContent;
import uk.gov.hmcts.ccd.domain.service.common.JcLogger;
import uk.gov.hmcts.ccd.domain.service.createcase.CreateCaseOperation;
import uk.gov.hmcts.ccd.domain.service.createevent.CreateEventOperation;
import uk.gov.hmcts.ccd.domain.service.getcase.CaseNotFoundException;
Expand Down Expand Up @@ -75,6 +76,8 @@
@Tag(name = "Standard case API")
public class CaseDetailsEndpoint {

private final JcLogger jclogger = new JcLogger("CaseDetailsEndpoint", true);

private final GetCaseOperation getCaseOperation;
private final CreateCaseOperation createCaseOperation;
private final CreateEventOperation createEventOperation;
Expand Down Expand Up @@ -188,7 +191,7 @@ public StartEventResult startEventForCaseworker(

@GetMapping(value = "/citizens/{uid}/jurisdictions/{jid}/case-types/{ctid}/cases/{cid}/event-triggers/{etid}/token")
@Operation(
summary = "Start event creation as Citizen",
summary = "Start event creation as Citizen",
description = "Start the event creation process for an existing case. Triggers `AboutToStart` callback."
)
@ApiResponses(value = {
Expand All @@ -215,7 +218,7 @@ public StartEventResult startEventForCitizen(

@GetMapping(value = "/caseworkers/{uid}/jurisdictions/{jid}/case-types/{ctid}/event-triggers/{etid}/token")
@Operation(
summary = "Start case creation as Case worker",
summary = "Start case creation as Case worker",
description = "Start the case creation process for a new case. Triggers `AboutToStart` callback."
)
@ApiResponses(value = {
Expand All @@ -239,7 +242,7 @@ public StartEventResult startCaseForCaseworker(

@GetMapping(value = "/citizens/{uid}/jurisdictions/{jid}/case-types/{ctid}/event-triggers/{etid}/token")
@Operation(
summary = "Start case creation as Citizen",
summary = "Start case creation as Citizen",
description = "Start the case creation process for a new case. Triggers `AboutToStart` callback."
)
@ApiResponses(value = {
Expand Down Expand Up @@ -431,7 +434,7 @@ public List<CaseDetails> searchCasesForCaseWorkers(
@PathVariable("jid") final String jurisdictionId,
@Parameter(name = "Case type ID", required = true)
@PathVariable("ctid") final String caseTypeId,
@Parameter(name = "Query Parameters",
@Parameter(name = "Query Parameters",
description = "Query Parameters, valid options: created_date, last_modified_date, "
+ "state, case_reference", required = false)
@RequestParam(required = false) Map<String, String> queryParameters) {
Expand All @@ -451,14 +454,25 @@ public List<CaseDetails> searchCasesForCitizens(@PathVariable("uid") final Strin
return searchCases(jurisdictionId, caseTypeId, queryParameters);
}

/*
* QUESTION: How is 'sanitizedParams' constructed in method searchCases() ?
*/
private List<CaseDetails> searchCases(final String jurisdictionId,
final String caseTypeId,
final Map<String, String> queryParameters) {

final MetaData metadata = createMetadata(jurisdictionId, caseTypeId, queryParameters);

jclogger.jclog("searchCases()", "jurisdictionId: " + jurisdictionId);
jclogger.jclog("searchCases()", "caseTypeId: " + caseTypeId);
jclogger.jclog("searchCases()",
"queryParameters: " + queryParameters.size());
jclogger.jclog("searchCases()",
"queryParameters: " + jclogger.printObjectToString(queryParameters));
final Map<String, String> sanitizedParams = fieldMapSanitizeOperation.execute(queryParameters);

jclogger.jclog("searchCases()", "sanitized: " + sanitizedParams.size());
jclogger.jclog("searchCases()", "sanitized: " + jclogger.printObjectToString(sanitizedParams));
return searchOperation.execute(metadata, sanitizedParams);
}

Expand Down
15 changes: 13 additions & 2 deletions src/main/java/uk/gov/hmcts/ccd/endpoint/ui/QueryEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import uk.gov.hmcts.ccd.domain.service.aggregated.GetEventTriggerOperation;
import uk.gov.hmcts.ccd.domain.service.aggregated.GetUserProfileOperation;
import uk.gov.hmcts.ccd.domain.service.aggregated.SearchQueryOperation;
import uk.gov.hmcts.ccd.domain.service.common.JcLogger;
import uk.gov.hmcts.ccd.endpoint.exceptions.BadRequestException;
import uk.gov.hmcts.ccd.endpoint.exceptions.ResourceNotFoundException;
import uk.gov.hmcts.ccd.v2.V2;
Expand Down Expand Up @@ -85,6 +86,7 @@ public class QueryEndpoint {
private static final Logger LOG = LoggerFactory.getLogger(QueryEndpoint.class);
public static final String CASE_TYPE_ID_PATTERN = "^[a-zA-Z0-9_.]+$";

private final JcLogger jclogger = new JcLogger("QueryEndpoint", true);

private final GetCaseViewOperation getCaseViewOperation;
private final GetCaseHistoryViewOperation getCaseHistoryViewOperation;
Expand Down Expand Up @@ -153,6 +155,9 @@ public List<JurisdictionDisplayProperties> getJurisdictions(@RequestParam(value
}
}

/*
* QUESTION: How is 'sanitized' constructed in method searchNew() ?
*/
@RequestMapping(value = "/caseworkers/{uid}/jurisdictions/{jid}/case-types/{ctid}/cases",
method = RequestMethod.GET)
@Operation(summary = "Get case data with UI layout")
Expand All @@ -179,8 +184,14 @@ public SearchResultView searchNew(@PathVariable("jid") final String jurisdiction
metadata.setPage(param(params, PAGE_PARAM));
metadata.setSortDirection(param(params, SORT_PARAM));

jclogger.jclog("searchNew()", "jurisdictionId: " + jurisdictionId);
jclogger.jclog("searchNew()", "caseTypeId: " + caseTypeId);
jclogger.jclog("searchNew()", "params: " + params.size());
jclogger.jclog("searchNew()", "params: " + jclogger.printObjectToString(params));
Map<String, String> sanitized = fieldMapSanitizeOperation.execute(params);

jclogger.jclog("searchNew()", "sanitized: " + sanitized.size());
jclogger.jclog("searchNew()", "sanitized: " + jclogger.printObjectToString(sanitized));
return searchQueryOperation.execute(view, metadata, sanitized);
}

Expand All @@ -207,11 +218,11 @@ public SearchInput[] findSearchInputDetails(@PathVariable("uid") final String ui
method = RequestMethod.GET)
@Operation(summary = "Get Workbasket Input details")
@ApiResponse(
responseCode = "200",
responseCode = "200",
description = "Workbasket Input data found for the given case type and jurisdiction"
)
@ApiResponse(
responseCode = "404",
responseCode = "404",
description = "No Workbasket Input found for the given case type and jurisdiction"
)
public WorkbasketInput[] findWorkbasketInputDetails(@PathVariable("uid") final String uid,
Expand Down