Skip to content

Commit cf4b0bd

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

File tree

14 files changed

+420
-91
lines changed

14 files changed

+420
-91
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-15
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package uk.gov.hmcts.ccd.domain.service.createevent;
22

33
import com.fasterxml.jackson.databind.JsonNode;
4-
import com.fasterxml.jackson.databind.ObjectMapper;
5-
import com.fasterxml.jackson.databind.node.ObjectNode;
4+
65
import java.util.Map;
76
import java.util.Optional;
87
import java.util.Set;
@@ -52,9 +51,7 @@ public MidEventCallback(CallbackInvoker callbackInvoker,
5251
}
5352

5453
@Transactional
55-
public JsonNode invoke(String caseTypeId,
56-
CaseDataContent content,
57-
String pageId) {
54+
public Map<String, JsonNode> invoke(String caseTypeId, CaseDataContent content, String pageId) {
5855
if (!isBlank(pageId)) {
5956
Event event = content.getEvent();
6057
final CaseTypeDefinition caseTypeDefinition = getCaseType(caseTypeId);
@@ -91,11 +88,10 @@ public JsonNode invoke(String caseTypeId,
9188
caseDetailsBefore,
9289
currentOrNewCaseDetails,
9390
content.getIgnoreWarning());
94-
95-
return dataJsonNode(caseDetailsFromMidEventCallback.getData());
91+
return caseDetailsFromMidEventCallback.getData();
9692
}
9793
}
98-
return dataJsonNode(content.getData());
94+
return content.getData();
9995
}
10096

10197
private void removeNextPageFieldData(CaseDetails currentCaseDetails, Integer order,
@@ -112,13 +108,6 @@ private void removeNextPageFieldData(CaseDetails currentCaseDetails, Integer ord
112108
}
113109
}
114110

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

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

+30
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
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 uk.gov.hmcts.ccd.config.JacksonUtils.DATA;
2021
import static uk.gov.hmcts.ccd.config.JacksonUtils.MAPPER;
2122

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

0 commit comments

Comments
 (0)