Skip to content

Commit 2967925

Browse files
committed
implement Classified to /validate endpoints
1 parent 72bf595 commit 2967925

File tree

14 files changed

+425
-89
lines changed

14 files changed

+425
-89
lines changed

build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ dependencies {
280280
testRuntimeOnly "org.junit.platform:junit-platform-commons:1.8.1"
281281
testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0'
282282
testImplementation group:'org.mockito', name: 'mockito-junit-jupiter', version:'3.6.0'
283+
testImplementation 'org.mockito:mockito-inline:4.11.0'
283284
testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: powermockVersion
284285
testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: powermockVersion
285286
testImplementation group: 'io.rest-assured', name: 'rest-assured', version: '4.3.0'

src/aat/resources/features/F-1017 - Validate Event to Update TTL/F-1017.feature

+14-8
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ Feature: F-1017: Validate Event to Update TTL
252252
# #CCD-3535 & #CCD-3562: Trigger a mid-event callback that makes permitted changes to the TTL values: v1_external#/citizen/case-details-endpoint/validateCaseDetailsUsingPOST_1
253253
#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
254254

255-
@S-1017.21 #CCD-3535
255+
@S-1017.21 @Ignore #CCD-3535
256256
Scenario: Trigger a mid event callback that changes TTL.Suspended (null -> missing). Mid Event is invoked on v1_external#/citizen/case-details-endpoint/validateCaseDetailsUsingPOST_1
257257
Given a user with [an active profile in CCD]
258258
And a user with [a caseworker with an active profile in CCD]
@@ -270,9 +270,11 @@ Feature: F-1017: Validate Event to Update TTL
270270

271271
Then a positive response is received
272272
And the response has all other details as expected
273-
And the response [does not contain the TTL as citizen user has no access]
273+
And the response [contains the TTL.SystemTTL for the case, that has been set to 20 days from today]
274+
And the response [contains the TTL.OverrideTTL from the previouse data]
275+
And the response [does not contain the TTL.Suspended as removed by callback (null -> missing)]
274276

275-
@S-1017.22 #CCD-3535
277+
@S-1017.22 @Ignore #CCD-3535
276278
Scenario: Trigger a mid event callback that changes TTL.Suspended (No -> NO). Mid Event is invoked on v1_external#/citizen/case-details-endpoint/validateCaseDetailsUsingPOST_1
277279
Given a user with [an active profile in CCD]
278280
And a user with [a caseworker with an active profile in CCD]
@@ -291,9 +293,11 @@ Feature: F-1017: Validate Event to Update TTL
291293

292294
Then a positive response is received
293295
And the response has all other details as expected
294-
And the response [does not contain the TTL as citizen user has no access]
296+
And the response [contains the TTL.SystemTTL for the case, that has been set to 20 days from today]
297+
And the response [does not contain the TTL.OverrideTTL as removed by callback (null -> missing)]
298+
And the response [contains the adjusted TTL.Suspended from the callback (No -> NO)]
295299

296-
@S-1017.23 #CCD-3535
300+
@S-1017.23 @Ignore #CCD-3535
297301
Scenario: Trigger a mid event callback that changes TTL.Suspended (Yes -> YES). Mid Event is invoked on v1_external#/citizen/case-details-endpoint/validateCaseDetailsUsingPOST_1
298302
Given a user with [an active profile in CCD]
299303
And a user with [a caseworker with an active profile in CCD]
@@ -312,10 +316,12 @@ Feature: F-1017: Validate Event to Update TTL
312316

313317
Then a positive response is received
314318
And the response has all other details as expected
315-
And the response [does not contain the TTL as citizen user has no access]
319+
And the response [contains the TTL.SystemTTL for the case, that has been set to 20 days from today]
320+
And the response [does not contain the TTL.OverrideTTL as removed by callback (null -> missing)]
321+
And the response [contains the adjusted TTL.Suspended from the callback (Yes -> YES)]
316322

317323

318-
@S-1017.25 #CCD-3562
324+
@S-1017.25 @Ignore #CCD-3562
319325
Scenario: Trigger a mid event callback that has TTL missing. Mid Event is invoked on v1_external#/citizen/case-details-endpoint/validateCaseDetailsUsingPOST_1
320326
Given a user with [an active profile in CCD]
321327
And a successful call [to create a case] as in [CreateCase_TTLCaseType_PreRequisiteCitizen]
@@ -329,7 +335,7 @@ Feature: F-1017: Validate Event to Update TTL
329335

330336
Then a positive response is received
331337
And the response has all other details as expected
332-
And the response [does not contain the TTL as citizen user has no access]
338+
And the response [contains the TTL.SystemTTL for the case, that has been set to 20 days from today]
333339

334340
@S-1017.26 #CCD-3562
335341
Scenario: Trigger a mid event callback that changes TTL set to null. Mid Event is invoked on v1_external#/citizen/case-details-endpoint/validateCaseDetailsUsingPOST_1

src/aat/resources/features/F-1017 - Validate Event to Update TTL/S-1017.21.td.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"has a TTLIncrement of 20 days configured",
1919
"is configured to trigger a mid event callback that changes the TTL.Suspended value (null -> missing)",
2020

21-
"does not contain the TTL as citizen user has no access"
21+
"contains the TTL.SystemTTL for the case, that has been set to 20 days from today",
22+
"contains the TTL.OverrideTTL from the previouse data",
23+
"does not contain the TTL.Suspended as removed by callback (null -> missing)"
2224
],
2325

2426
"users": {

src/aat/resources/features/F-1017 - Validate Event to Update TTL/S-1017.22.td.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
"is configured to trigger a mid event callback that changes the TTL.OverrideTTL value (null -> missing)",
2020
"is configured to trigger a mid event callback that changes the TTL.Suspended value (No -> NO)",
2121

22-
"does not contain the TTL as citizen user has no access"
22+
"contains the TTL.SystemTTL for the case, that has been set to 20 days from today",
23+
"does not contain the TTL.OverrideTTL as removed by callback (null -> missing)",
24+
"contains the adjusted TTL.Suspended from the callback (No -> NO)"
2325
],
2426

2527
"users": {

src/aat/resources/features/F-1017 - Validate Event to Update TTL/S-1017.23.td.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
"is configured to trigger a mid event callback that changes the TTL.OverrideTTL value (null -> missing)",
2020
"is configured to trigger a mid event callback that changes the TTL.Suspended value (Yes -> YES)",
2121

22-
"does not contain the TTL as citizen user has no access"
22+
"contains the TTL.SystemTTL for the case, that has been set to 20 days from today",
23+
"does not contain the TTL.OverrideTTL as removed by callback (null -> missing)",
24+
"contains the adjusted TTL.Suspended from the callback (Yes -> YES)"
2325
],
2426

2527
"users": {

src/aat/resources/features/F-1017 - Validate Event to Update TTL/S-1017.25.td.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"has a TTLIncrement of 20 days configured",
1717
"is configured to trigger a mid event callback that responds with TTL missing",
1818

19-
"does not contain the TTL as citizen user has no access"
19+
"contains the TTL.SystemTTL for the case, that has been set to 20 days from today"
2020
],
2121

2222
"users": {

src/main/java/uk/gov/hmcts/ccd/domain/service/createevent/MidEventCallback.java

+4-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import uk.gov.hmcts.ccd.domain.model.definition.WizardPage;
2222
import uk.gov.hmcts.ccd.domain.model.std.CaseDataContent;
2323
import uk.gov.hmcts.ccd.domain.model.std.Event;
24+
import uk.gov.hmcts.ccd.domain.service.common.CaseDataService;
2425
import uk.gov.hmcts.ccd.domain.service.common.CaseService;
2526
import uk.gov.hmcts.ccd.domain.service.common.EventTriggerService;
2627
import uk.gov.hmcts.ccd.domain.service.stdapi.CallbackInvoker;
@@ -52,9 +53,7 @@ public MidEventCallback(CallbackInvoker callbackInvoker,
5253
}
5354

5455
@Transactional
55-
public JsonNode invoke(String caseTypeId,
56-
CaseDataContent content,
57-
String pageId) {
56+
public Map<String, JsonNode> invoke(String caseTypeId, CaseDataContent content, String pageId) {
5857
if (!isBlank(pageId)) {
5958
Event event = content.getEvent();
6059
final CaseTypeDefinition caseTypeDefinition = getCaseType(caseTypeId);
@@ -91,11 +90,10 @@ public JsonNode invoke(String caseTypeId,
9190
caseDetailsBefore,
9291
currentOrNewCaseDetails,
9392
content.getIgnoreWarning());
94-
95-
return dataJsonNode(caseDetailsFromMidEventCallback.getData());
93+
return caseDetailsFromMidEventCallback.getData();
9694
}
9795
}
98-
return dataJsonNode(content.getData());
96+
return content.getData();
9997
}
10098

10199
private void removeNextPageFieldData(CaseDetails currentCaseDetails, Integer order,
@@ -112,13 +110,6 @@ private void removeNextPageFieldData(CaseDetails currentCaseDetails, Integer ord
112110
}
113111
}
114112

115-
private JsonNode dataJsonNode(Map<String, JsonNode> data) {
116-
ObjectMapper mapper = new ObjectMapper();
117-
ObjectNode objectNode = mapper.createObjectNode();
118-
objectNode.set("data", mapper.valueToTree(data));
119-
return objectNode;
120-
}
121-
122113
private CaseTypeDefinition getCaseType(String caseTypeId) {
123114
final CaseTypeDefinition caseTypeDefinition = caseDefinitionRepository.getCaseType(caseTypeId);
124115
if (caseTypeDefinition == null) {

src/main/java/uk/gov/hmcts/ccd/domain/service/validate/AuthorisedValidateCaseFieldsOperation.java

+3-14
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import uk.gov.hmcts.ccd.domain.model.std.CaseDataContent;
1414
import uk.gov.hmcts.ccd.domain.service.common.AccessControlService;
1515
import uk.gov.hmcts.ccd.domain.service.common.CaseAccessService;
16-
import uk.gov.hmcts.ccd.domain.service.createevent.MidEventCallback;
1716
import uk.gov.hmcts.ccd.endpoint.exceptions.ValidationException;
1817

1918
import java.util.Map;
@@ -32,20 +31,17 @@ public class AuthorisedValidateCaseFieldsOperation implements ValidateCaseFields
3231
private final CaseDefinitionRepository caseDefinitionRepository;
3332
private final CaseAccessService caseAccessService;
3433
private final ValidateCaseFieldsOperation validateCaseFieldsOperation;
35-
private final MidEventCallback midEventCallback;
3634

3735
public AuthorisedValidateCaseFieldsOperation(AccessControlService accessControlService,
3836
@Qualifier(CachedCaseDefinitionRepository.QUALIFIER)
3937
CaseDefinitionRepository caseDefinitionRepository,
4038
CaseAccessService caseAccessService,
41-
@Qualifier(DefaultValidateCaseFieldsOperation.QUALIFIER)
42-
ValidateCaseFieldsOperation validateCaseFieldsOperation,
43-
MidEventCallback midEventCallback) {
39+
@Qualifier(ClassifiedValidateCaseFieldsOperation.QUALIFIER)
40+
ValidateCaseFieldsOperation validateCaseFieldsOperation) {
4441
this.accessControlService = accessControlService;
4542
this.caseDefinitionRepository = caseDefinitionRepository;
4643
this.caseAccessService = caseAccessService;
4744
this.validateCaseFieldsOperation = validateCaseFieldsOperation;
48-
this.midEventCallback = midEventCallback;
4945
}
5046

5147
@Override
@@ -54,13 +50,6 @@ public Map<String, JsonNode> validateCaseDetails(OperationContext operationConte
5450

5551
CaseDataContent content = operationContext.content();
5652
String caseTypeId = operationContext.caseTypeId();
57-
String pageId = operationContext.pageId();
58-
59-
final JsonNode data = midEventCallback.invoke(caseTypeId,
60-
content,
61-
pageId);
62-
63-
content.setData(JacksonUtils.convertValue(data));
6453

6554
String caseReference = content.getCaseReference();
6655
Set<AccessProfile> accessProfiles = StringUtils.isNotEmpty(caseReference)
@@ -91,7 +80,7 @@ private void verifyReadAccess(final String caseTypeId, CaseDataContent content,
9180

9281
content.setData(JacksonUtils.convertValueInDataField(
9382
accessControlService.filterCaseFieldsByAccess(
94-
JacksonUtils.convertValueJsonNode(content.getData().get(JacksonUtils.DATA)),
83+
JacksonUtils.convertValueJsonNode(content.getData()),
9584
caseTypeDefinition.getCaseFieldDefinitions(),
9685
accessProfiles,
9786
CAN_READ,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package uk.gov.hmcts.ccd.domain.service.validate;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.google.common.collect.Maps;
5+
import org.apache.commons.lang3.StringUtils;
6+
import org.apache.logging.log4j.util.Strings;
7+
import org.springframework.beans.factory.annotation.Qualifier;
8+
import org.springframework.stereotype.Service;
9+
import uk.gov.hmcts.ccd.data.definition.CachedCaseDefinitionRepository;
10+
import uk.gov.hmcts.ccd.data.definition.CaseDefinitionRepository;
11+
import uk.gov.hmcts.ccd.domain.model.definition.CaseDetails;
12+
import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeDefinition;
13+
import uk.gov.hmcts.ccd.domain.model.std.CaseDataContent;
14+
import uk.gov.hmcts.ccd.domain.service.common.CaseDataService;
15+
import uk.gov.hmcts.ccd.domain.service.common.CaseService;
16+
import uk.gov.hmcts.ccd.domain.service.common.SecurityClassificationServiceImpl;
17+
import uk.gov.hmcts.ccd.domain.service.createevent.MidEventCallback;
18+
import uk.gov.hmcts.ccd.endpoint.exceptions.ValidationException;
19+
20+
import java.util.HashMap;
21+
import java.util.Map;
22+
23+
import static com.google.common.collect.Maps.newHashMap;
24+
import static java.util.Optional.ofNullable;
25+
26+
@Service
27+
@Qualifier(ClassifiedValidateCaseFieldsOperation.QUALIFIER)
28+
public class ClassifiedValidateCaseFieldsOperation implements ValidateCaseFieldsOperation {
29+
public static final String QUALIFIER = "classified";
30+
private static final HashMap<String, JsonNode> EMPTY_DATA_CLASSIFICATION = Maps.newHashMap();
31+
32+
33+
private final ValidateCaseFieldsOperation validateCaseFieldsOperation;
34+
private final SecurityClassificationServiceImpl classificationService;
35+
private final MidEventCallback midEventCallback;
36+
private final CaseDataService caseDataService;
37+
private final CaseDefinitionRepository caseDefinitionRepository;
38+
private final CaseService caseService;
39+
40+
41+
42+
public ClassifiedValidateCaseFieldsOperation(@Qualifier(DefaultValidateCaseFieldsOperation.QUALIFIER)
43+
ValidateCaseFieldsOperation ValidateCaseFieldsOperation,
44+
SecurityClassificationServiceImpl classificationService,
45+
MidEventCallback midEventCallback, CaseDataService caseDataService,
46+
@Qualifier(CachedCaseDefinitionRepository.QUALIFIER)
47+
CaseDefinitionRepository caseDefinitionRepository, CaseService caseService) {
48+
this.validateCaseFieldsOperation = ValidateCaseFieldsOperation;
49+
this.classificationService = classificationService;
50+
this.midEventCallback = midEventCallback;
51+
this.caseDataService = caseDataService;
52+
this.caseDefinitionRepository = caseDefinitionRepository;
53+
this.caseService = caseService;
54+
}
55+
56+
@Override
57+
public Map<String, JsonNode> validateCaseDetails(OperationContext operationContext) {
58+
validateCaseFieldsOperation.validateCaseDetails(operationContext);
59+
60+
CaseDataContent content = operationContext.content();
61+
String caseTypeId = operationContext.caseTypeId();
62+
String pageId = operationContext.pageId();
63+
64+
65+
final Map<String, JsonNode> callbackData = midEventCallback.invoke(caseTypeId,
66+
content,
67+
pageId);
68+
69+
CaseTypeDefinition caseTypeDefinition = getCaseDefinitionType(caseTypeId);
70+
71+
CaseDetails caseDetails;
72+
boolean isCreate;
73+
if (StringUtils.isNotEmpty(content.getCaseReference())) {
74+
isCreate = false;
75+
caseDetails =
76+
caseService.getCaseDetails(caseTypeDefinition.getJurisdictionId(), content.getCaseReference());
77+
} else {
78+
isCreate = true;
79+
caseDetails = new CaseDetails();
80+
caseDetails.setCaseTypeId(caseTypeId);
81+
caseDetails.setSecurityClassification(caseTypeDefinition.getSecurityClassification());
82+
}
83+
84+
caseDetails.setData(callbackData);
85+
deduceDataClassificationForNewFields(caseTypeDefinition, caseDetails);
86+
87+
CaseDetails classifiedCaseDetails =
88+
classificationService.applyClassification(caseDetails, isCreate).orElse(new CaseDetails());
89+
90+
content.setData(classifiedCaseDetails.getData());
91+
92+
return content.getData();
93+
}
94+
95+
@Override
96+
public void validateData(Map<String, JsonNode> data, CaseTypeDefinition caseTypeDefinition,
97+
CaseDataContent content) {
98+
validateCaseFieldsOperation.validateData(data, caseTypeDefinition, content);
99+
}
100+
101+
private CaseTypeDefinition getCaseDefinitionType(String caseTypeId) {
102+
final CaseTypeDefinition caseTypeDefinition = caseDefinitionRepository.getCaseType(caseTypeId);
103+
if (caseTypeDefinition == null) {
104+
throw new ValidationException("Cannot find case type definition for " + caseTypeId);
105+
}
106+
return caseTypeDefinition;
107+
}
108+
109+
110+
private void deduceDataClassificationForNewFields(CaseTypeDefinition caseTypeDefinition, CaseDetails caseDetails) {
111+
Map<String, JsonNode> defaultSecurityClassifications = caseDataService.getDefaultSecurityClassifications(
112+
caseTypeDefinition,
113+
caseDetails.getData(),
114+
ofNullable(caseDetails.getDataClassification()).orElse(
115+
newHashMap()));
116+
caseDetails.setDataClassification(defaultSecurityClassifications);
117+
}
118+
}

src/main/java/uk/gov/hmcts/ccd/domain/service/validate/ValidateCaseFieldsOperation.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
public interface ValidateCaseFieldsOperation {
1010

11-
Map<String, JsonNode> validateCaseDetails(OperationContext validationContext);
11+
Map<String, JsonNode> validateCaseDetails(OperationContext operationContext);
1212

1313
void validateData(final Map<String, JsonNode> data,
1414
final CaseTypeDefinition caseTypeDefinition,

src/test/java/uk/gov/hmcts/ccd/config/JacksonUtilsTest.java

+31
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818
import static org.junit.jupiter.api.Assertions.assertNotNull;
1919
import static org.junit.jupiter.api.Assertions.assertNull;
20+
import static org.mockito.ArgumentMatchers.any;
21+
import static uk.gov.hmcts.ccd.config.JacksonUtils.DATA;
2022
import static uk.gov.hmcts.ccd.config.JacksonUtils.MAPPER;
2123

2224
class JacksonUtilsTest {
@@ -405,4 +407,33 @@ static Map<String, JsonNode> organisationPolicyDefaultValue(String role)
405407
result.put("OrganisationPolicyField", data);
406408
return result;
407409
}
410+
411+
@Test
412+
void testConvertValueInDataField() throws JsonProcessingException {
413+
JsonNode jsonNode = MAPPER.readTree("""
414+
{
415+
"Name": "Name_1",
416+
"Class": [
417+
{
418+
"id": "6da7a0cf-8186-49d4-813d-c299d8f3491b",
419+
"value": {
420+
"ClassName": "Class_1"
421+
}
422+
},
423+
{
424+
"id": "b7662626-b640-48bb-8afa-9fa78dcbd2ec",
425+
"value": {
426+
"ClassName": "Class_2"
427+
}
428+
}
429+
],
430+
"Number": null
431+
}
432+
""");
433+
434+
Map<String, JsonNode> result = JacksonUtils.convertValueInDataField(jsonNode);
435+
436+
assertEquals(1, result.size());
437+
assertEquals(jsonNode, result.get(DATA));
438+
}
408439
}

0 commit comments

Comments
 (0)