diff --git a/Dockerfile b/Dockerfile index b6102e759..e4958db95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ -ARG APP_INSIGHTS_AGENT_VERSION=3.2.4 +ARG APP_INSIGHTS_AGENT_VERSION=3.4.9 ARG PLATFORM="" # Application image FROM hmctspublic.azurecr.io/base/java${PLATFORM}:17-distroless -COPY lib/AI-Agent.xml /opt/app/ +COPY lib/applicationinsights.json /opt/app/ COPY build/libs/rd-caseworker-ref-api.jar /opt/app/ EXPOSE 8095 diff --git a/build.gradle b/build.gradle index 05cca8541..5f79b28aa 100644 --- a/build.gradle +++ b/build.gradle @@ -16,9 +16,9 @@ plugins { id 'pmd' id 'com.github.ben-manes.versions' version '0.43.0' id "info.solidsoft.pitest" version '1.7.0' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'io.spring.dependency-management' version '1.1.0' id 'org.sonarqube' version '3.3' - id 'org.springframework.boot' version '2.4.9' + id 'org.springframework.boot' version '2.7.7' id "org.flywaydb.flyway" version '8.5.4' id 'au.com.dius.pact' version '4.1.7' // do not change, otherwise serenity report fails id 'org.owasp.dependencycheck' version '8.0.1' @@ -34,11 +34,10 @@ def versions = [ gradlePitest : '1.5.1', pitest : '1.7.0', reformHealthStarter: '0.0.5', - reformLogging : '5.1.9', + reformLogging : '6.0.1', serenity : '2.0.76', sonarPitest : '0.5', - springBoot : '2.6.7', - springfoxSwagger : '2.9.2', + springBoot : '2.7.7', pact_version : '4.1.7', launchDarklySdk : "5.10.2", restAssured : '4.3.3', @@ -47,7 +46,7 @@ def versions = [ springVersion : '5.3.20', poi : '4.1.2', logback : '1.2.11', - testContainer_postgresql: '1.17.2' + testContainer_postgresql: '1.17.6' ] mainClassName = 'uk.gov.hmcts.reform.cwrdapi.CaseWorkerRefApiApplication' @@ -363,14 +362,11 @@ dependencies { exclude group: "org.apache.sling" } implementation group: 'com.sun.xml.bind', name: 'jaxb-osgi', version: '2.3.3' - implementation group: 'io.springfox', name: 'springfox-swagger2', version: versions.springfoxSwagger - implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: versions.springfoxSwagger - implementation 'com.github.hmcts:service-auth-provider-java-client:4.0.3' implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: versions.jackson implementation group: 'io.jsonwebtoken', name: 'jjwt', version:'0.9.1' - implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: versions.jackson + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: versions.jackson implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: versions.jackson implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: versions.jackson implementation group: 'com.fasterxml.jackson', name: 'jackson-bom', version: '2.13.2.20220324', ext: 'pom' @@ -379,7 +375,7 @@ dependencies { implementation 'com.github.hmcts:idam-java-client:2.0.1' implementation "org.springframework.boot:spring-boot-starter-oauth2-client" implementation "org.springframework.boot:spring-boot-starter-oauth2-resource-server" - implementation group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '8.20' + implementation group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '9.25' implementation 'org.springframework.boot:spring-boot-starter-validation' @@ -387,6 +383,8 @@ dependencies { implementation group: 'org.postgresql', name: 'postgresql', version: '42.5.1' implementation group: 'com.google.guava', name: 'guava', version: '31.1-jre' + //Added org.glassfish to support javax.el + implementation group: 'org.glassfish', name: 'javax.el', version: '3.0.0' implementation group: 'javax.el', name: 'javax.el-api', version: '3.0.0' implementation group: 'org.yaml', name: 'snakeyaml', version: '1.33' implementation group: 'com.launchdarkly', name: 'launchdarkly-java-server-sdk', version: '5.10.2' @@ -408,10 +406,13 @@ dependencies { implementation "io.github.openfeign:feign-httpclient:11.0" implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: versions.log4j implementation "com.github.hmcts.java-logging:logging:${versions.reformLogging}" - implementation "com.github.hmcts.java-logging:logging-appinsights:${versions.reformLogging}" + implementation "com.github.hmcts.java-logging:logging-appinsights:5.1.9" implementation group: 'com.vladmihalcea', name: 'hibernate-types-52', version: '2.19.2' implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-jaxb-annotations', version: '2.13.4' implementation group: 'org.yaml', name: 'snakeyaml', version: '1.33' + + implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.8' + implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-bootstrap', version: '3.1.5' // https://mvnrepository.com/artifact/net.minidev/json-smart implementation group: 'net.minidev', name: 'json-smart', version: '2.4.8' @@ -458,7 +459,7 @@ dependencies { } testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.12.7' testImplementation group: 'net.bytebuddy', name: 'byte-buddy-agent', version: '1.12.7' - testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' + testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9' testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '4.3.1' testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.1' @@ -479,10 +480,6 @@ dependencies { testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock:3.1.0' testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: versions.springBoot testImplementation('com.opentable.components:otj-pg-embedded:0.13.4') - testImplementation group: 'org.codehaus.groovy', name: 'groovy', version: '3.0.10' - testImplementation group: 'org.codehaus.groovy', name: 'groovy-xml', version: '2.5.14' -// https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-json - implementation group: 'org.codehaus.groovy', name: 'groovy-json', version: '3.0.15' testImplementation group: 'org.springframework', name: 'spring-test', version: '5.3.17' testImplementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.10' testImplementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.10' @@ -566,6 +563,12 @@ bootJar { } configurations.all { resolutionStrategy.eachDependency { details -> +// added netty-tcnative-boringssl-static because its required for +// group: 'com.azure', name: 'azure-core', version: '1.13.0' in spring boot upgrade + if (details.requested.group == 'io.netty' + && details.requested.name == 'netty-tcnative-boringssl-static' ){ + details.useVersion "2.0.35.Final" + } if (details.requested.group == 'io.netty' && details.requested.name != 'netty-tcnative-boringssl-static' ) { details.useVersion "4.1.86.Final" diff --git a/charts/rd-caseworker-ref-api/Chart.yaml b/charts/rd-caseworker-ref-api/Chart.yaml index bb41a689a..63dec8733 100644 --- a/charts/rd-caseworker-ref-api/Chart.yaml +++ b/charts/rd-caseworker-ref-api/Chart.yaml @@ -3,7 +3,7 @@ appVersion: "1.0" description: A Helm chart for rd-caseworker-ref-api name: rd-caseworker-ref-api home: https://github.com/hmcts/rd-caseworker-ref-api -version: 0.0.27 +version: 0.0.28 maintainers: - name: Reference Data Team dependencies: diff --git a/charts/rd-caseworker-ref-api/values.yaml b/charts/rd-caseworker-ref-api/values.yaml index c91f5afbc..b10596958 100644 --- a/charts/rd-caseworker-ref-api/values.yaml +++ b/charts/rd-caseworker-ref-api/values.yaml @@ -28,8 +28,8 @@ java: secrets: - name: caseworker-ref-api-POSTGRES-PASS alias: POSTGRES_PASSWORD - - name: ApplicationInsightsInstrumentationKey - alias: azure.application-insights.instrumentation-key + - name: app-insights-connection-string + alias: app-insights-connection-string - name: caseworker-topic-primary-send-listen-shared-access-key alias: CASEWORKER_TOPIC_PRIMARY_SEND_LISTEN_SHARED_ACCESS_KEY - name: caseworker-ref-api-s2s-secret diff --git a/lib/AI-Agent.xml b/lib/AI-Agent.xml deleted file mode 100644 index a5cdcfe38..000000000 --- a/lib/AI-Agent.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - INFO - - - - - - - diff --git a/lib/applicationinsights-agent-2.5.1-BETA.jar b/lib/applicationinsights-agent-2.5.1-BETA.jar deleted file mode 100644 index 74dfa3ea5..000000000 Binary files a/lib/applicationinsights-agent-2.5.1-BETA.jar and /dev/null differ diff --git a/lib/applicationinsights.json b/lib/applicationinsights.json new file mode 100644 index 000000000..37fdbe959 --- /dev/null +++ b/lib/applicationinsights.json @@ -0,0 +1,6 @@ +{ + "connectionString": "${file:/mnt/secrets/rd/app-insights-connection-string}", + "role": { + "name": "RD Caseworker Ref API" + } +} diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CaseWorkerCreateUserWithFileUploadTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CaseWorkerCreateUserWithFileUploadTest.java index 6179ecfdf..db4608d9f 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CaseWorkerCreateUserWithFileUploadTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CaseWorkerCreateUserWithFileUploadTest.java @@ -368,7 +368,6 @@ public void shouldCreateCaseWorkerAuditUpFailure() throws IOException { + "\"error_details\":[{\"row_id\":\"2\"," + "\"error_description\":\"User creation is not possible at this moment. " + "Please try again later or check with administrator.\"}]}"; - response = uploadCaseWorkerFile("Staff Data Upload.xlsx", TYPE_XLSX, "200 OK", cwdAdmin); String json = getJsonResponse(response); diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileBasicSearchTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileBasicSearchTest.java index e0297abfe..a65d27c3d 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileBasicSearchTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileBasicSearchTest.java @@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.PAGE_NUMBER; import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.PAGE_SIZE; +import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.ROLE_CWD_ADMIN; public class CreateStaffReferenceProfileBasicSearchTest extends AuthorizationEnabledIntegrationTest { @@ -42,7 +43,6 @@ public class CreateStaffReferenceProfileBasicSearchTest extends AuthorizationEna public static final String CASE_WORKER_PROFILE_URL = "/refdata/case-worker/profile"; public static final String EMAIL_TEMPLATE = "CWR-func-test-user-%s@justice.gov.uk"; - public static final String ROLE_CWD_ADMIN = "cwd-admin"; public static final String ROLE_STAFF_ADMIN = "staff-admin"; diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileIntegrationTest.java index b8edd70eb..b4bc0c1ae 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateStaffReferenceProfileIntegrationTest.java @@ -38,11 +38,10 @@ import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.INVALID_EMAIL; import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.NO_PRIMARY_LOCATION_PRESENT_PROFILE; import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.NO_PRIMARY_ROLE_PRESENT_PROFILE; +import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.ROLE_STAFF_ADMIN; public class CreateStaffReferenceProfileIntegrationTest extends AuthorizationEnabledIntegrationTest { - public static final String ROLE_STAFF_ADMIN = "staff-admin"; - @Autowired CaseWorkerProfileRepository caseWorkerProfileRepository; @Autowired diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateUpdateStaffRefDataProfilesIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateUpdateStaffRefDataProfilesIntegrationTest.java index bed93a053..18b6fdcb5 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateUpdateStaffRefDataProfilesIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/CreateUpdateStaffRefDataProfilesIntegrationTest.java @@ -56,17 +56,18 @@ public void setUpClient() { //Set up Case worker data Set roles = ImmutableSet.of(" tribunal_case_worker "); List caseWorkerRoleRequests = - ImmutableList.of(CaseWorkerRoleRequest.caseWorkerRoleRequest().role(" role ").isPrimaryFlag(true).build()); + ImmutableList.of(CaseWorkerRoleRequest.caseWorkerRoleRequest() + .role(" role ").isPrimaryFlag(true).build()); List caseWorkerLocationRequests = ImmutableList.of(CaseWorkerLocationRequest - .caseWorkersLocationRequest() - .isPrimaryFlag(true).locationId(1) - .location(" location ").build()); + .caseWorkersLocationRequest() + .isPrimaryFlag(true).locationId(1) + .location(" location ").build()); List caseWorkerAreaRequests = ImmutableList.of(CaseWorkerWorkAreaRequest - .caseWorkerWorkAreaRequest() - .areaOfWork(" areaOfWork ").serviceCode(" serviceCode ") - .build()); + .caseWorkerWorkAreaRequest() + .areaOfWork(" areaOfWork ").serviceCode(" serviceCode ") + .build()); caseWorkersProfileCreationRequests = ImmutableList.of(CaseWorkersProfileCreationRequest .caseWorkersProfileCreationRequest() @@ -153,18 +154,18 @@ void shouldCreateCaseworkerWithNewRoles() { List caseWorkerRoleRequests = ImmutableList - .of(cwRoleRequest,cwRoleRequest1,cwRoleRequest2,cwRoleRequest3); + .of(cwRoleRequest, cwRoleRequest1, cwRoleRequest2, cwRoleRequest3); caseWorkersProfileCreationRequests.get(0).setRoles(caseWorkerRoleRequests); caseWorkersProfileCreationRequests.get(0).setUserType("Other Government Department"); Map response = caseworkerReferenceDataClient - .createCaseWorkerProfile(caseWorkersProfileCreationRequests, "cwd-admin"); + .createCaseWorkerProfile(caseWorkersProfileCreationRequests, "cwd-admin"); assertThat(response).containsEntry("http_status", "201 CREATED"); List caseWorkerRoles = caseWorkerRoleRepository.findAll(); assertEquals(13, (long) caseWorkerRoles.get(0).getRoleId()); - assertEquals(14,(long)caseWorkerRoles.get(2).getRoleId()); - assertEquals(16,(long)caseWorkerRoles.get(3).getRoleId()); + assertEquals(14, (long) caseWorkerRoles.get(2).getRoleId()); + assertEquals(16, (long) caseWorkerRoles.get(3).getRoleId()); var caseWorkerProfile = caseWorkerProfileRepository.findAll(); - assertEquals(5,caseWorkerProfile.get(0).getUserTypeId()); + assertEquals(5, caseWorkerProfile.get(0).getUserTypeId()); } } diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/FetchStaffProfileByIdIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/FetchStaffProfileByIdIntegrationTest.java index 84f74f350..f4b29e399 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/FetchStaffProfileByIdIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/FetchStaffProfileByIdIntegrationTest.java @@ -25,8 +25,8 @@ import static org.apache.logging.log4j.util.Strings.EMPTY; import static org.assertj.core.api.Assertions.assertThat; -import static uk.gov.hmcts.reform.cwrdapi.CreateStaffReferenceProfileBasicSearchTest.ROLE_CWD_ADMIN; -import static uk.gov.hmcts.reform.cwrdapi.UpdateStaffReferenceProfileTest.ROLE_STAFF_ADMIN; +import static uk.gov.hmcts.reform.cwrdapi.StaffReferenceProfileAdvanceIntegrationSearchTest.ROLE_STAFF_ADMIN; +import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.ROLE_CWD_ADMIN; public class FetchStaffProfileByIdIntegrationTest extends AuthorizationEnabledIntegrationTest { diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/StaffReferenceProfileAdvanceIntegrationSearchTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/StaffReferenceProfileAdvanceIntegrationSearchTest.java index a3fe82f91..d88131f38 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/StaffReferenceProfileAdvanceIntegrationSearchTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/StaffReferenceProfileAdvanceIntegrationSearchTest.java @@ -142,7 +142,7 @@ void should_return_staff_user_with_status_code_200_when_flag_enabled_with_pagina .role("task supervisor,case allocator,staff administrator") .skill("9") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @@ -167,7 +167,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_serviceCode( searchReq = SearchRequest.builder() .serviceCode("ABA1") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @Test @@ -191,7 +191,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_list_of_serv searchReq = SearchRequest.builder() .serviceCode("ABA1,serviceCode2") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @Test @@ -214,7 +214,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_location() { searchReq = SearchRequest.builder() .location("12345") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @@ -240,7 +240,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_list_of_loca searchReq = SearchRequest.builder() .location("12345,6789") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @Test @@ -265,7 +265,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_userType() { searchReq = SearchRequest.builder() .userType("1") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @Test @@ -290,7 +290,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_Jobtitle() { searchReq = SearchRequest.builder() .jobTitle("2") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @@ -316,7 +316,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_role() { searchReq = SearchRequest.builder() .role("task supervisor") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @Test @@ -341,7 +341,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_skill() { searchReq = SearchRequest.builder() .skill("9") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @@ -355,7 +355,7 @@ void should_return_staff_user_with_status_code_200_when_skill_are_empty() { .createStaffProfileCreationRequest(); staffProfileCreationRequest.setSkills(null); Map staffProfileResponse = caseworkerReferenceDataClient - .createStaffProfile(staffProfileCreationRequest,ROLE_STAFF_ADMIN); + .createStaffProfile(staffProfileCreationRequest, ROLE_STAFF_ADMIN); assertThat(staffProfileResponse).containsEntry("http_status", "201 CREATED"); @@ -380,8 +380,8 @@ void should_return_staff_user_with_status_code_200_when_skill_are_empty() { @ParameterizedTest - @ValueSource(strings = {"serviceCode=sddd","location=127494","userType=12","jobTitle=4224", - "role=staff administrator","skill=132"}) + @ValueSource(strings = {"serviceCode=sddd", "location=127494", "userType=12", "jobTitle=4224", + "role=staff administrator", "skill=132"}) void should_return_staff_user_with_status_code_200_with_empty_search_response(String searchString) { createCaseWorkerProfiles(); @@ -419,7 +419,7 @@ void should_return_staff_user_with_status_code_200_when_search_with_list_of_role searchReq = SearchRequest.builder() .role("task supervisor,case allocator,staff administrator") .build(); - assertTrue(validateSearchUserProfileResponse(response,searchReq)); + assertTrue(validateSearchUserProfileResponse(response, searchReq)); } @@ -450,8 +450,8 @@ void should_return_status_code_400_when_page_num_is_zero() { } @ParameterizedTest - @ValueSource(strings = {"","serviceCode=*_sd","location=1adf*_","userType=1sdfs*__","jobTitle=asdfs", - "role=task_supervisor","skill=asdfd"}) + @ValueSource(strings = {"", "serviceCode=*_sd", "location=1adf*_", "userType=1sdfs*__", "jobTitle=asdfs", + "role=task_supervisor", "skill=asdfd"}) void should_return_status_code_400(String searchString) { String path = "/profile/search?"; @@ -468,14 +468,14 @@ public void createCaseWorkerTestData() { StaffProfileCreationRequest staffProfileCreationRequest = caseworkerReferenceDataClient .createStaffProfileCreationRequest(); Map response = caseworkerReferenceDataClient - .createStaffProfile(staffProfileCreationRequest,ROLE_STAFF_ADMIN); + .createStaffProfile(staffProfileCreationRequest, ROLE_STAFF_ADMIN); assertThat(response).containsEntry("http_status", "201 CREATED"); } private void createCaseWorkerProfiles() { - IntStream.range(0,5).forEach(i -> createCaseWorkerTestData()); + IntStream.range(0, 5).forEach(i -> createCaseWorkerTestData()); } } \ No newline at end of file diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/UpdateStaffReferenceProfileTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/UpdateStaffReferenceProfileTest.java index 10eb75cd1..dbf9a6a87 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/UpdateStaffReferenceProfileTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/UpdateStaffReferenceProfileTest.java @@ -41,10 +41,10 @@ import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.INVALID_PROFILE; import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.NO_PRIMARY_LOCATION_PRESENT_PROFILE; import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.NO_PRIMARY_ROLE_PRESENT_PROFILE; +import static uk.gov.hmcts.reform.cwrdapi.util.CaseWorkerConstants.ROLE_STAFF_ADMIN; public class UpdateStaffReferenceProfileTest extends AuthorizationEnabledIntegrationTest { - public static final String ROLE_STAFF_ADMIN = "staff-admin"; @Autowired CaseWorkerProfileRepository caseWorkerProfileRepository; diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/docs/SwaggerPublisherTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/docs/SwaggerPublisherTest.java index 20a4e66be..3d94f1abe 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/docs/SwaggerPublisherTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/docs/SwaggerPublisherTest.java @@ -1,15 +1,14 @@ package uk.gov.hmcts.reform.cwrdapi.docs; +import net.thucydides.core.annotations.WithTag; +import net.thucydides.core.annotations.WithTags; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.context.WebApplicationContext; -import uk.gov.hmcts.reform.cwrdapi.config.SwaggerConfiguration; +import uk.gov.hmcts.reform.cwrdapi.util.AuthorizationEnabledIntegrationTest; import java.io.OutputStream; import java.nio.file.Files; @@ -23,10 +22,8 @@ * Built-in feature which saves service's swagger specs in temporary directory. * Each travis run on master should automatically save and upload (if updated) documentation. */ -@WebMvcTest -@ContextConfiguration(classes = SwaggerConfiguration.class) -@AutoConfigureMockMvc -class SwaggerPublisherTest { +@WithTags({@WithTag("testType:Integration")}) +class SwaggerPublisherTest extends AuthorizationEnabledIntegrationTest { private MockMvc mvc; @@ -42,7 +39,7 @@ public void setUp() { @Test @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") void generateDocs() throws Exception { - byte[] specs = mvc.perform(get("/v2/api-docs")) + byte[] specs = mvc.perform(get("/v3/api-docs")) .andExpect(status().isOk()) .andReturn() .getResponse() diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/AuthorizationEnabledIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/AuthorizationEnabledIntegrationTest.java index 042276715..de8d6de39 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/AuthorizationEnabledIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/AuthorizationEnabledIntegrationTest.java @@ -18,6 +18,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; +import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import uk.gov.hmcts.reform.authorisation.generators.AuthTokenGenerator; @@ -80,7 +81,7 @@ public abstract class AuthorizationEnabledIntegrationTest extends SpringBootInte public static WireMockExtension userProfileService = new WireMockExtension(8091); @RegisterExtension - public static WireMockExtension sidamService = new WireMockExtension(5000,new CaseWorkerTransformer()); + public static WireMockExtension sidamService = new WireMockExtension(5000, new CaseWorkerTransformer()); @RegisterExtension public static WireMockExtension mockHttpServerForOidc = new WireMockExtension(7000); @@ -106,6 +107,9 @@ public abstract class AuthorizationEnabledIntegrationTest extends SpringBootInte @Autowired Flyway flyway; + @MockBean + protected static JwtDecoder jwtDecoder; + @BeforeEach public void setUpClient() { when(featureToggleServiceImpl.isFlagEnabled(anyString(), anyString())).thenReturn(true); @@ -245,6 +249,7 @@ public void userProfilePostUserWireMock() { @AfterEach public void cleanupTestData() { + JwtDecoderMockBuilder.resetJwtDecoder(); } diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerReferenceDataClient.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerReferenceDataClient.java index f74f82982..b339bb59e 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerReferenceDataClient.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerReferenceDataClient.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTParser; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.impl.TextCodec; @@ -21,6 +23,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.RestClientResponseException; @@ -35,14 +38,18 @@ import uk.gov.hmcts.reform.cwrdapi.controllers.request.StaffProfileRoleRequest; import uk.gov.hmcts.reform.cwrdapi.controllers.response.SearchStaffUserResponse; +import java.text.ParseException; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; import static java.lang.String.format; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; import static org.springframework.http.HttpMethod.DELETE; import static org.springframework.http.MediaType.APPLICATION_JSON; import static uk.gov.hmcts.reform.cwrdapi.util.JwtTokenUtil.generateToken; @@ -79,6 +86,9 @@ public CaseWorkerReferenceDataClient(int port) { this.baseInternalUrl = "http://localhost:" + port + APP_INTERNAL_BASE_PATH; } + public CaseWorkerReferenceDataClient() { + } + public Map createCaseWorkerProfile(CaseWorkersProfileCreationRequest request, String role) { return postRequest(baseUrl + "/users/", request, role, null); } @@ -150,7 +160,6 @@ private ResponseEntity getRequest(String uriPath, Class clasz, String ro } - public Map fetchStaffProfileByCcdServiceName(String ccdServiceNames, Integer pageSize, Integer pageNumber, String sortDirection, String sortColumn, String role) { @@ -185,7 +194,7 @@ public Map fetchStaffProfileByCcdServiceName(String ccdServiceNa try { responseEntity = restTemplate.exchange( - baseInternalUrl + stringBuilder.toString(), + baseInternalUrl + stringBuilder.toString(), HttpMethod.GET, request, Map.class ); @@ -200,9 +209,9 @@ public Map fetchStaffProfileByCcdServiceName(String ccdServiceNa return getResponse(responseEntity); } - public Map searchStaffUserByName(String path,String searchString, String pageSize, + public Map searchStaffUserByName(String path, String searchString, String pageSize, - String pageNumber, String role) { + String pageNumber, String role) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder .append(path); @@ -212,7 +221,7 @@ public Map searchStaffUserByName(String path,String searchString stringBuilder.append(searchString); } - HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null,pageNumber,pageSize); + HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null, pageNumber, pageSize); ResponseEntity responseEntity; HttpEntity request = @@ -222,7 +231,7 @@ public Map searchStaffUserByName(String path,String searchString try { responseEntity = restTemplate.exchange( - baseUrl + stringBuilder.toString(), + baseUrl + stringBuilder.toString(), HttpMethod.GET, request, Map.class ); @@ -238,7 +247,7 @@ public Map searchStaffUserByName(String path,String searchString } public ResponseEntity searchStaffUserByNameExchange( - String path,String searchString, String pageSize, String pageNumber, String role) { + String path, String searchString, String pageSize, String pageNumber, String role) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder .append(path); @@ -248,7 +257,7 @@ public ResponseEntity searchStaffUserByNameExchange( stringBuilder.append(searchString); } - HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null,pageNumber,pageSize); + HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null, pageNumber, pageSize); ResponseEntity responseEntity = null; HttpEntity request = @@ -257,7 +266,7 @@ public ResponseEntity searchStaffUserByNameExchange( try { responseEntity = restTemplate.exchange( - baseUrl + stringBuilder.toString(), + baseUrl + stringBuilder.toString(), HttpMethod.GET, request, SearchStaffUserResponse[].class ); @@ -270,7 +279,7 @@ public ResponseEntity searchStaffUserByNameExchange( } public ResponseEntity> searchStaffUserExchange( - String path,String searchString, String pageSize, String pageNumber, String role) { + String path, String searchString, String pageSize, String pageNumber, String role) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder .append(path); @@ -279,7 +288,7 @@ public ResponseEntity> searchStaffUserExchange( stringBuilder.append(searchString); } - HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null,pageNumber,pageSize); + HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null, pageNumber, pageSize); ResponseEntity> responseEntity = null; HttpEntity request = @@ -302,7 +311,7 @@ public ResponseEntity> searchStaffUserExchange( } public Map searchStaffUser( - String path,String searchString, String pageSize, String pageNumber, String role) { + String path, String searchString, String pageSize, String pageNumber, String role) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder .append(path); @@ -311,7 +320,7 @@ public Map searchStaffUser( stringBuilder.append(searchString); } - HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null,pageNumber,pageSize); + HttpHeaders headers = getMultipleAuthHeadersWithPagination(role, null, pageNumber, pageSize); ResponseEntity responseEntity; HttpEntity request = @@ -320,7 +329,7 @@ public Map searchStaffUser( try { responseEntity = restTemplate.exchange( - baseUrl + stringBuilder.toString(), + baseUrl + stringBuilder.toString(), HttpMethod.GET, request, Map.class ); @@ -442,7 +451,74 @@ private HttpHeaders getMultipleAuthHeadersWithPagination( } + public String setAndReturnJwtToken() { + if (StringUtils.isBlank(JWT_TOKEN)) { + JWT_TOKEN = generateS2SToken("rd_caseworker_ref_api"); + } + return JWT_TOKEN; + } + + + public void clearTokens() { + JWT_TOKEN = null; + bearerToken = null; + } + public Map bearerTokenMap = new HashMap<>(); + + public String getAndReturnBearerToken(String userId, String role) { + String bearerToken; + if (bearerTokenMap.get(role) == null && userId != null) { + bearerToken = "Bearer ".concat(getBearerToken(Objects.isNull(userId) ? UUID.randomUUID().toString() + : userId, role)); + bearerTokenMap.put(role, bearerToken); + } else if (bearerTokenMap.get(role + userId) == null) { + bearerToken = "Bearer ".concat(getBearerToken(userId, role)); + bearerTokenMap.put(role + userId, bearerToken); + return bearerToken; + } + if (userId == null) { + return bearerTokenMap.get(role + userId); + } + return bearerTokenMap.get(role); + } + + public synchronized void mockJwtToken(String role, String userId, String bearerToken) { + String[] bearerTokenArray = bearerToken.split(" "); + when(JwtDecoderMockBuilder.getJwtDecoder().decode(anyString())).thenReturn(decode(bearerTokenArray[1])); + } + + private Jwt createJwt(String token, JWT parsedJwt) { + Jwt jwt = null; + try { + Map headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject()); + Map claims = new HashMap<>(); + for (String key : parsedJwt.getJWTClaimsSet().getClaims().keySet()) { + Object value = parsedJwt.getJWTClaimsSet().getClaims().get(key); + if (key.equals("exp") || key.equals("iat")) { + value = ((Date) value).toInstant(); + } + claims.put(key, value); + } + jwt = Jwt.withTokenValue(token) + .headers(h -> h.putAll(headers)) + .claims(c -> c.putAll(claims)) + .build(); + } catch (Exception ex) { + System.out.println(ex); + } + return jwt; + } + + public Jwt decode(String token) { + JWT jwt = null; + try { + jwt = JWTParser.parse(token); + } catch (ParseException e) { + throw new RuntimeException(e); + } + return createJwt(token, jwt); + } @NotNull private HttpHeaders getMultipleAuthHeadersWithoutContentType(String role, String userId) { @@ -454,10 +530,8 @@ private HttpHeaders getMultipleAuthHeadersWithoutContentType(String role, String headers.add("ServiceAuthorization", JWT_TOKEN); - if (StringUtils.isBlank(bearerToken)) { - bearerToken = "Bearer ".concat(getBearerToken(Objects.isNull(userId) ? UUID.randomUUID().toString() - : userId, role)); - } + String bearerToken = getAndReturnBearerToken(userId, role); + mockJwtToken(role, userId, bearerToken); headers.add("Authorization", bearerToken); return headers; } @@ -533,7 +607,7 @@ public StaffProfileCreationRequest createStaffProfileCreationRequest() { List caseWorkerLocationRequests = ImmutableList.of(CaseWorkerLocationRequest .caseWorkersLocationRequest() .isPrimaryFlag(true).locationId(12345) - .location("test location").build(),CaseWorkerLocationRequest + .location("test location").build(), CaseWorkerLocationRequest .caseWorkersLocationRequest() .isPrimaryFlag(true).locationId(6789) .location("test location2").build()); @@ -541,7 +615,7 @@ public StaffProfileCreationRequest createStaffProfileCreationRequest() { List caseWorkerServicesRequests = ImmutableList.of(CaseWorkerServicesRequest .caseWorkerServicesRequest() .service("Immigration and Asylum Appeals").serviceCode("serviceCode2") - .build(),CaseWorkerServicesRequest + .build(), CaseWorkerServicesRequest .caseWorkerServicesRequest() .service("Divorce").serviceCode("ABA1") .build()); @@ -553,7 +627,7 @@ public StaffProfileCreationRequest createStaffProfileCreationRequest() { .description("testskill1") .build()); - return StaffProfileCreationRequest + return StaffProfileCreationRequest .staffProfileCreationRequest() .firstName("StaffProfilefirstName") .lastName("StaffProfilelastName") diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/JwtDecoderMockBuilder.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/JwtDecoderMockBuilder.java new file mode 100644 index 000000000..b9d8e11a9 --- /dev/null +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/JwtDecoderMockBuilder.java @@ -0,0 +1,15 @@ +package uk.gov.hmcts.reform.cwrdapi.util; + + +import org.springframework.security.oauth2.jwt.JwtDecoder; + +public class JwtDecoderMockBuilder extends AuthorizationEnabledIntegrationTest { + + public static void resetJwtDecoder() { + jwtDecoder = null; + } + + public static synchronized JwtDecoder getJwtDecoder() { + return jwtDecoder; + } +} diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/KeyGenUtil.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/KeyGenUtil.java index 7564b079f..970d19532 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/KeyGenUtil.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/KeyGenUtil.java @@ -5,7 +5,6 @@ import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; -import net.minidev.json.JSONObject; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -31,8 +30,8 @@ public static RSAKey getRsaJwk() throws JOSEException { public static String getDynamicJwksResponse() throws JOSEException, JsonProcessingException { RSAKey rsaKey = KeyGenUtil.getRsaJwk(); - Map> body = new LinkedHashMap<>(); - List keyList = new ArrayList<>(); + Map>> body = new LinkedHashMap<>(); + List> keyList = new ArrayList<>(); keyList.add(rsaKey.toJSONObject()); body.put("keys", keyList); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/SpringBootIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/SpringBootIntegrationTest.java index 4aced08c6..9c5eee38a 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/SpringBootIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/cwrdapi/util/SpringBootIntegrationTest.java @@ -2,7 +2,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.junit.jupiter.SpringExtension; import uk.gov.hmcts.reform.cwrdapi.CaseWorkerRefApiApplication; diff --git a/src/integrationTest/resources/application-test.yml b/src/integrationTest/resources/application-test.yml index 2ac62a8a7..64a591df6 100644 --- a/src/integrationTest/resources/application-test.yml +++ b/src/integrationTest/resources/application-test.yml @@ -27,6 +27,7 @@ spring: time_zone: UTC main: allow-bean-definition-overriding: true + allow-circular-references: true application: name: RD Caseworker Ref API security: @@ -78,7 +79,9 @@ security: - "/loggers/**" - "/swagger-ui.html" - "/swagger-resources/**" - - "/v2/api-docs" + - "/v3/api-docs" + - "/swagger-ui/**" + - "/v3/**" - "/webjars/springfox-swagger-ui/**" - "/csrf" - "/error" diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/client/domain/CaseWorkerProfile.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/client/domain/CaseWorkerProfile.java index f8a82e41c..c0344fb14 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/client/domain/CaseWorkerProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/client/domain/CaseWorkerProfile.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -42,11 +43,13 @@ public class CaseWorkerProfile extends CaseWorkerDomain implements Serializable @MappingField(columnName = "First Name") @Pattern(regexp = NAME_REGEX, message = FIRST_NAME_INVALID) @NotEmpty(message = FIRST_NAME_MISSING) + @Schema(name = "firstName", example = "string") private String firstName; @MappingField(columnName = "Last Name") @Pattern(regexp = NAME_REGEX, message = LAST_NAME_INVALID) @NotEmpty(message = LAST_NAME_MISSING) + @Schema(name = "lastName", example = "string") private String lastName; @MappingField(columnName = "Email", position = 1) diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SecurityConfiguration.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SecurityConfiguration.java index 88c1a2eb4..7506b8f24 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SecurityConfiguration.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SecurityConfiguration.java @@ -7,9 +7,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenValidator; @@ -21,6 +20,7 @@ import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter; +import org.springframework.security.web.SecurityFilterChain; import uk.gov.hmcts.reform.authorisation.filters.ServiceAuthFilter; import uk.gov.hmcts.reform.cwrdapi.oidc.JwtGrantedAuthoritiesConverter; @@ -34,14 +34,14 @@ @EnableWebSecurity @Slf4j @SuppressWarnings("unchecked") -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { - +public class SecurityConfiguration { @Value("${spring.security.oauth2.client.provider.oidc.issuer-uri}") private String issuerUri; @Value("${oidc.issuer}") private String issuerOverride; + @Order(1) private ServiceAuthFilter serviceAuthFilter; @Order(2) @@ -60,10 +60,9 @@ public void setAnonymousPaths(List anonymousPaths) { this.anonymousPaths = anonymousPaths; } - @Override - public void configure(WebSecurity web) { - web.ignoring() - .antMatchers(anonymousPaths.toArray(new String[0])); + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return web -> web.ignoring().antMatchers(anonymousPaths.toArray(String[]::new)); } @Inject @@ -77,29 +76,29 @@ public SecurityConfiguration(final JwtGrantedAuthoritiesConverter jwtGrantedAuth jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter); this.securityEndpointFilter = securityEndpointFilter; - } - @Override - protected void configure(final HttpSecurity http) throws Exception { - http - .addFilterBefore(serviceAuthFilter, BearerTokenAuthenticationFilter.class) - .addFilterAfter(securityEndpointFilter, OAuth2AuthorizationRequestRedirectFilter.class) - .sessionManagement().sessionCreationPolicy(STATELESS).and() - .csrf().disable() - .formLogin().disable() - .logout().disable() - .authorizeRequests() - .antMatchers("/error").permitAll() - .anyRequest() - .authenticated() - .and() - .oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint) - .jwt() - .jwtAuthenticationConverter(jwtAuthenticationConverter) - .and() - .and() - .oauth2Client(); + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.addFilterBefore(serviceAuthFilter, BearerTokenAuthenticationFilter.class) + .addFilterAfter(securityEndpointFilter, OAuth2AuthorizationRequestRedirectFilter.class) + + .sessionManagement().sessionCreationPolicy(STATELESS).and() + .csrf().disable() + .formLogin().disable() + .logout().disable() + .authorizeRequests() + .antMatchers("/error").permitAll() + .anyRequest() + .authenticated() + .and() + .oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint) + .jwt() + .jwtAuthenticationConverter(jwtAuthenticationConverter) + .and() + .and() + .oauth2Client(); + return http.build(); } @Bean @@ -114,5 +113,3 @@ JwtDecoder jwtDecoder() { return jwtDecoder; } } - - diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SwaggerConfiguration.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SwaggerConfiguration.java index 60caf7fb3..5cea6e328 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SwaggerConfiguration.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/config/SwaggerConfiguration.java @@ -1,42 +1,51 @@ package uk.gov.hmcts.reform.cwrdapi.config; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.parameters.Parameter; +import org.springdoc.core.GroupedOpenApi; +import org.springdoc.core.customizers.OperationCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.bind.annotation.RestController; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiKey; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.List; -import java.util.Optional; - -import static com.google.common.collect.Lists.newArrayList; +import org.springframework.web.method.HandlerMethod; @Configuration -@EnableSwagger2 +@SecurityScheme(name = "Authorization", type = SecuritySchemeType.HTTP, bearerFormat = "JWT", scheme = "bearer") +@SecurityScheme(name = "ServiceAuthorization", type = SecuritySchemeType.APIKEY, + in = SecuritySchemeIn.HEADER, bearerFormat = "JWT", description = "ServiceAuthorization") public class SwaggerConfiguration { @Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2) - .useDefaultResponseMessages(false) - .genericModelSubstitutes(Optional.class) - .select() - .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) - .paths(PathSelectors.any()) - .build() - .securitySchemes(apiKeyList()); + public GroupedOpenApi publicApi(OperationCustomizer customGlobalHeaders) { + return GroupedOpenApi.builder() + .group("rd-caseworker-ref-api") + .pathsToMatch("/**") + .build(); } - private List apiKeyList() { - return - newArrayList( - new ApiKey("Authorization", "Authorization","header"), - new ApiKey("ServiceAuthorization", "ServiceAuthorization", "header") - ); + @Bean + public OperationCustomizer customGlobalHeaders() { + return (Operation customOperation, HandlerMethod handlerMethod) -> { + Parameter serviceAuthorizationHeader = new Parameter() + .in(ParameterIn.HEADER.toString()) + .schema(new StringSchema()) + .name("ServiceAuthorization") + .description("Keyword `Bearer` followed " + + "by a service-to-service token for a whitelisted micro-service") + .required(true); + Parameter authorizationHeader = new Parameter() + .in(ParameterIn.HEADER.toString()) + .schema(new StringSchema()) + .name("Authorization") + .description("Authorization token") + .required(true); + customOperation.addParametersItem(authorizationHeader); + customOperation.addParametersItem(serviceAuthorizationHeader); + return customOperation; + }; } - } diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefController.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefController.java index 855cfa2a2..a2f614ebd 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefController.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefController.java @@ -1,9 +1,11 @@ package uk.gov.hmcts.reform.cwrdapi.controllers; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -53,72 +55,83 @@ public class CaseWorkerRefController { CaseWorkerServiceFacade caseWorkerServiceFacade; - @ApiOperation( - value = "This API allows uploading of excel files that contain caseworker information " + @Operation( + summary = "This API allows uploading of excel files that contain caseworker information " + "and mappings between caseworker and IDAM roles", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + description = "This API will be invoked by user having idam role of cwd-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 201, - message = REQUEST_COMPLETED_SUCCESSFULLY + responseCode = "201", + description = REQUEST_COMPLETED_SUCCESSFULLY, + content = @Content ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @PostMapping(value = "/upload-file", consumes = "multipart/form-data") @Secured("cwd-admin") - public ResponseEntity caseWorkerFileUpload(@RequestParam(FILE) MultipartFile file) { + public ResponseEntity caseWorkerFileUpload(@RequestParam(FILE) MultipartFile file) { return caseWorkerServiceFacade.processFile(file); } - @ApiOperation( + @Operation( hidden = true, - value = "This API builds the idam role mappings for case worker roles", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + summary = "This API builds the idam role mappings for case worker roles", + description = "This API will be invoked by user having idam role of cwd-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 201, - message = "Successfully built idam role mappings for case worker roles", - response = IdamRolesMappingResponse.class + responseCode = "201", + description = "Successfully built idam role mappings for case worker roles", + content = @Content(schema = @Schema(implementation = IdamRolesMappingResponse.class)) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @PostMapping( diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefUsersController.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefUsersController.java index e8f931840..d4683c859 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefUsersController.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/CaseWorkerRefUsersController.java @@ -1,9 +1,12 @@ package uk.gov.hmcts.reform.cwrdapi.controllers; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -76,36 +79,40 @@ public class CaseWorkerRefUsersController { @Autowired CaseWorkerDeleteService caseWorkerDeleteService; - @ApiOperation( + @Operation( hidden = true, - value = "This API creates caseworker profiles", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + summary = "This API creates caseworker profiles", + description = "This API will be invoked by user having idam role of cwd-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 201, - message = "Successfully created caseworker user profiles", - response = String.class, - responseContainer = "list" + responseCode = "201", + description = "Successfully created caseworker user profiles", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class))) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @PostMapping( @@ -147,38 +154,44 @@ public ResponseEntity createCaseWorkerProfiles(@RequestBody List fetchCaseworkersById(@RequestBody UserRequest user } - @ApiOperation(value = "Delete Case Worker Profiles by User ID or Email Pattern", - notes = "This API is only for use in non Prod environments", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation(summary = "Delete Case Worker Profiles by User ID or Email Pattern", + description = "This API is only for use in non Prod environments", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") }) @ApiResponses({ @ApiResponse( - code = 204, - message = "Case Worker Profiles deleted successfully", - response = CaseWorkerProfilesDeletionResponse.class + responseCode = "204", + description = "Case Worker Profiles deleted successfully", + content = @Content(schema = @Schema(implementation = CaseWorkerProfilesDeletionResponse.class)) ), @ApiResponse( - code = 400, - message = "An invalid request has been provided" + responseCode = "400", + description = "An invalid request has been provided", + content = @Content ), @ApiResponse( - code = 401, - message = "Unauthorized Error : The requested resource is restricted and requires authentication" + responseCode = "401", + description = "Unauthorized Error : " + + "The requested resource is restricted and requires authentication", + content = @Content ), @ApiResponse( - code = 403, - message = "Forbidden Error: Access denied" + responseCode = "403", + description = "Forbidden Error: Access denied", + content = @Content ), @ApiResponse( - code = 500, - message = "Internal Server Error" + responseCode = "500", + description = "Internal Server Error", + content = @Content ) }) diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/StaffRefDataController.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/StaffRefDataController.java index 373c5d222..c61e441ae 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/StaffRefDataController.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/StaffRefDataController.java @@ -1,12 +1,16 @@ package uk.gov.hmcts.reform.cwrdapi.controllers; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springdoc.api.annotations.ParameterObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; @@ -55,7 +59,6 @@ import static uk.gov.hmcts.reform.cwrdapi.util.RequestUtils.validateSearchString; - @RequestMapping( path = "/refdata/case-worker" ) @@ -80,44 +83,49 @@ public class StaffRefDataController { @Autowired StaffRefDataService staffRefDataService; - @ApiOperation( - - value = "This API allows the search of staff user by their name or surname.", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") - } + @Operation( + summary = "This API allows the search of staff user by their name or surname.", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") + } ) @ApiResponses({ - @ApiResponse( - code = 201, - message = REQUEST_COMPLETED_SUCCESSFULLY - ), - @ApiResponse( - code = 400, - message = BAD_REQUEST - ), - @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR - ), - @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR - ), - @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR - ) + @ApiResponse( + responseCode = "200", + description = REQUEST_COMPLETED_SUCCESSFULLY, + content = @Content(schema = @Schema(implementation = SearchStaffUserResponse.class)) + ), + @ApiResponse( + responseCode = "400", + description = BAD_REQUEST, + content = @Content + ), + @ApiResponse( + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content + ), + @ApiResponse( + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content + ), + @ApiResponse( + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content + ) }) @Validated @GetMapping(path = "/profile/search-by-name", - produces = APPLICATION_JSON_VALUE) + produces = APPLICATION_JSON_VALUE) @Secured("staff-admin") public ResponseEntity> searchStaffUserByName( - @RequestHeader(name = "page-number", required = false) Integer pageNumber, - @RequestHeader(name = "page-size", required = false) Integer pageSize, - @RequestParam(value = "search") @NotEmpty @NotNull String searchString) { + @RequestHeader(name = "page-number", required = false) Integer pageNumber, + @RequestHeader(name = "page-size", required = false) Integer pageSize, + @RequestParam(value = "search") @NotEmpty @NotNull String searchString) { validateSearchString(removeEmptySpaces(searchString)); var pageRequest = validateAndBuildPagination(pageSize, pageNumber, configPageSize, configPageNumber); @@ -127,32 +135,35 @@ public ResponseEntity> searchStaffUserByName( } - @ApiOperation( + @Operation( - value = "This API is used to retrieve the service specific skills ", - notes = "This API will be invoked by user having idam role of staff-admin", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + summary = "This API is used to retrieve the service specific skills ", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 200, - message = "Successfully retrieved list of ServiceSkills for the request provided", - response = StaffWorkerSkillResponse.class + responseCode = "200", + description = "Successfully retrieved list of ServiceSkills for the request provided", + content = @Content(schema = @Schema(implementation = StaffWorkerSkillResponse.class)) ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @GetMapping( @@ -161,7 +172,7 @@ public ResponseEntity> searchStaffUserByName( ) @Secured("staff-admin") public ResponseEntity retrieveAllServiceSkills( - @RequestParam(value = "service_codes", required = false) String serviceCodes + @RequestParam(value = "service_codes", required = false) String serviceCodes ) { log.info("StaffRefDataController.retrieveAllServiceSkills Calling Service layer"); @@ -170,29 +181,33 @@ public ResponseEntity retrieveAllServiceSkills( return ResponseEntity.ok().body(staffWorkerSkillResponse); } - @ApiOperation( - value = "This API gets the user types from staff reference data", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API gets the user types from staff reference data", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") }) @ApiResponses({ @ApiResponse( - code = 200, - message = "Successfully fetched the user types", - response = StaffRefDataUserTypesResponse.class + responseCode = "200", + description = "Successfully fetched the user types", + content = @Content(schema = @Schema(implementation = StaffRefDataUserTypesResponse.class)) ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @GetMapping( @@ -216,31 +231,34 @@ public ResponseEntity fetchUserTypes() { } - @ApiOperation( - value = "This API is used to retrieve the Job Title's ", - notes = "This API will be invoked by user having idam role of staff-admin", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API is used to retrieve the Job Title's ", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 200, - message = "Successfully retrieved list of Job Titles for the request provided", - response = StaffRefJobTitleResponse.class + responseCode = "200", + description = "Successfully retrieved list of Job Titles for the request provided", + content = @Content(schema = @Schema(implementation = StaffRefJobTitleResponse.class)) ), @ApiResponse( - code = 400, - message = "Bad Request" + responseCode = "400", + description = "Bad Request", + content = @Content ), @ApiResponse( - code = 401, - message = "Forbidden Error: Access denied" + responseCode = "401", + description = "Forbidden Error: Access denied", + content = @Content ), @ApiResponse( - code = 500, - message = "Internal Server Error" + responseCode = "500", + description = "Internal Server Error", + content = @Content ) }) @GetMapping( @@ -265,36 +283,40 @@ public ResponseEntity retrieveJobTitles() { } - @ApiOperation( - value = "This API creates staff user profile", - notes = "This API will be invoked by user having idam role with cwd-admin and staff-admin", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API creates staff user profile", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 201, - message = "Successfully created staff user profile", - response = StaffProfileCreationResponse.class, - responseContainer = "list" + responseCode = "201", + description = "Successfully created staff user profile", + content = @Content(array = + @ArraySchema(schema = @Schema(implementation = StaffProfileCreationResponse.class))) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @PostMapping( @@ -320,33 +342,40 @@ public ResponseEntity createStaffUserProfile(@Requ return ResponseEntity.status(HttpStatus.CREATED).body(staffProfileCreationResponse); } - @ApiOperation( - value = "This API allows the Advance search of staff", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API allows the Advance search of staff", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 200, - message = REQUEST_COMPLETED_SUCCESSFULLY + responseCode = "200", + description = REQUEST_COMPLETED_SUCCESSFULLY, + content = @Content(array = + @ArraySchema(schema = @Schema(implementation = SearchStaffUserResponse.class))) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @Validated @@ -356,43 +385,47 @@ public ResponseEntity createStaffUserProfile(@Requ public ResponseEntity> searchStaffProfile( @RequestHeader(name = "page-number", required = false) Integer pageNumber, @RequestHeader(name = "page-size", required = false) Integer pageSize, - SearchRequest searchRequest) { + @ParameterObject SearchRequest searchRequest) { validateSearchRequest(searchRequest); var pageRequest = validateAndBuildPagination(pageSize, pageNumber, configPageSize, configPageNumber); return staffRefDataService.retrieveStaffProfile(searchRequest, pageRequest); } - @ApiOperation( - value = "This API updates staff user profile", - notes = "This API will be invoked by user having idam role with staff-admin", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API updates staff user profile", + description = "This API will be invoked by user having idam role with staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 200, - message = "Successfully updated staff user profile", - response = StaffProfileCreationResponse.class, - responseContainer = "list" + responseCode = "200", + description = "Successfully updated staff user profile", + content = @Content(array = + @ArraySchema(schema = @Schema(implementation = StaffProfileCreationResponse.class))) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @PutMapping( @@ -421,34 +454,39 @@ public ResponseEntity updateStaffUserProfile(@Requ return ResponseEntity.status(HttpStatus.OK).body(staffProfileCreationResponse); } - @ApiOperation( - value = "This API search a staff user by Id", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API search a staff user by Id", + description = "This API will be invoked by user having idam role of staff-admin", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 200, - message = "Request is successful", - response = SearchStaffUserByIdResponse.class + responseCode = "200", + description = "Request is successful", + content = @Content(schema = @Schema(implementation = SearchStaffUserByIdResponse.class)) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @GetMapping( diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/WelcomeController.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/WelcomeController.java index 3ea101dfe..284e061d0 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/WelcomeController.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/WelcomeController.java @@ -1,9 +1,11 @@ package uk.gov.hmcts.reform.cwrdapi.controllers; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.CacheControl; @@ -45,12 +47,12 @@ public class WelcomeController { */ - @ApiOperation("Welcome message for the Caseworker Ref Data API") + @Operation(summary = "Welcome message for the Caseworker Ref Data API") @ApiResponses({ - @ApiResponse( - code = 200, - message = "Welcome message", - response = String.class + @ApiResponse( + responseCode = "200", + description = "Welcome message", + content = @Content(schema = @Schema(implementation = String.class)) ) }) @GetMapping( diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/internal/StaffReferenceInternalController.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/internal/StaffReferenceInternalController.java index f5f9bcbf6..03ca0f986 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/internal/StaffReferenceInternalController.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/internal/StaffReferenceInternalController.java @@ -1,9 +1,11 @@ package uk.gov.hmcts.reform.cwrdapi.controllers.internal; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -55,39 +57,45 @@ public class StaffReferenceInternalController { @Autowired CaseWorkerService caseWorkerService; - @ApiOperation( - value = "This API returns the Staff(Case Worker) profiles based on Service Name and Pagination parameters", - notes = "**IDAM Role to access API** :\n cwd-system-user", - authorizations = { - @Authorization(value = "ServiceAuthorization"), - @Authorization(value = "Authorization") + @Operation( + summary = "This API returns the Staff(Case Worker) " + + "profiles based on Service Name and Pagination parameters", + description = "**IDAM Role to access API** :\n cwd-system-user", + security = { + @SecurityRequirement(name = "ServiceAuthorization"), + @SecurityRequirement(name = "Authorization") } ) @ApiResponses({ @ApiResponse( - code = 200, - message = "The Staff profiles have been retrieved successfully", - response = StaffProfileWithServiceName.class + responseCode = "200", + description = "The Staff profiles have been retrieved successfully", + content = @Content(schema = @Schema(implementation = StaffProfileWithServiceName.class)) ), @ApiResponse( - code = 400, - message = BAD_REQUEST + responseCode = "400", + description = BAD_REQUEST, + content = @Content ), @ApiResponse( - code = 401, - message = UNAUTHORIZED_ERROR + responseCode = "401", + description = UNAUTHORIZED_ERROR, + content = @Content ), @ApiResponse( - code = 403, - message = FORBIDDEN_ERROR + responseCode = "403", + description = FORBIDDEN_ERROR, + content = @Content ), @ApiResponse( - code = 404, - message = NO_DATA_FOUND + responseCode = "404", + description = NO_DATA_FOUND, + content = @Content ), @ApiResponse( - code = 500, - message = INTERNAL_SERVER_ERROR + responseCode = "500", + description = INTERNAL_SERVER_ERROR, + content = @Content ) }) @GetMapping( diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/SearchRequest.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/SearchRequest.java index a19441a6a..0b9f80ed9 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/SearchRequest.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/SearchRequest.java @@ -1,6 +1,6 @@ package uk.gov.hmcts.reform.cwrdapi.controllers.request; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -12,22 +12,22 @@ @AllArgsConstructor public class SearchRequest { - @ApiParam(name = "serviceCode", value = "Any Valid String is allowed with comma seperated values") + @Parameter(name = "serviceCode", description = "Any Valid String is allowed with comma seperated values") String serviceCode; - @ApiParam(name = "location", value = "Any Valid String is allowed with comma seperated values") + @Parameter(name = "location", description = "Any Valid String is allowed with comma seperated values") String location; - @ApiParam(name = "userType", value = "Any Valid String is allowed") + @Parameter(name = "userType", description = "Any Valid String is allowed") String userType; - @ApiParam(name = "jobTitle", value = "Any Valid String is allowed") + @Parameter(name = "jobTitle", description = "Any Valid String is allowed") String jobTitle; - @ApiParam(name = "skill", value = "Any Valid String is allowed") + @Parameter(name = "skill", description = "Any Valid String is allowed") String skill; - @ApiParam(name = "role", value = "Any Valid String is allowed with comma seperated values") + @Parameter(name = "role", description = "Any Valid String is allowed with comma seperated values") String role; } diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/StaffProfileCreationRequest.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/StaffProfileCreationRequest.java index abc3f2195..3eed002b1 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/StaffProfileCreationRequest.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/controllers/request/StaffProfileCreationRequest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -40,11 +41,13 @@ public class StaffProfileCreationRequest { @JsonProperty("first_name") @Pattern(regexp = NAME_REGEX, message = FIRST_NAME_INVALID) @NotEmpty(message = FIRST_NAME_MISSING_PROFILE) + @Schema(name = "firstName", example = "string") private String firstName; @JsonProperty("last_name") @Pattern(regexp = NAME_REGEX, message = LAST_NAME_INVALID) @NotEmpty(message = LAST_NAME_MISSING_PROFILE) + @Schema(name = "lastName", example = "string") private String lastName; @JsonProperty("services") diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverter.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverter.java index ce173dc5c..c04b978ff 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverter.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverter.java @@ -43,7 +43,7 @@ public JwtGrantedAuthoritiesConverter(IdamRepository idamRepository) { @Override public Collection convert(Jwt jwt) { List authorities = new ArrayList<>(); - if (TRUE.equals(jwt.containsClaim(TOKEN_NAME)) && jwt.getClaim(TOKEN_NAME).equals(ACCESS_TOKEN)) { + if (TRUE.equals(jwt.hasClaim(TOKEN_NAME)) && jwt.getClaim(TOKEN_NAME).equals(ACCESS_TOKEN)) { userInfo = idamRepository.getUserInfo(jwt.getTokenValue()); authorities = extractAuthorityFromClaims(userInfo.getRoles()); diff --git a/src/main/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerConstants.java b/src/main/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerConstants.java index 564938c48..16856146a 100644 --- a/src/main/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerConstants.java +++ b/src/main/java/uk/gov/hmcts/reform/cwrdapi/util/CaseWorkerConstants.java @@ -125,6 +125,8 @@ private CaseWorkerConstants() { + "Please try again or check with HMCTS Support Team"; public static final String ROLE_CWD_USER = "cwd-user"; public static final String ROLE_STAFF_ADMIN = "staff-admin"; + public static final String ROLE_CWD_SYSTEM_USER = "cwd-system-user"; + public static final String ROLE_CWD_ADMIN = "cwd-admin"; public static final String DUPLICATE_PRIMARY_AND_SECONDARY_ROLES = "Primary and Secondary Roles Should " + "not be same."; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b6cd8b530..ebcf1f446 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -29,6 +29,7 @@ spring: name: RD Caseworker Ref API main: allow-bean-definition-overriding: true + allow-circular-references: true security: oauth2: client: @@ -91,8 +92,10 @@ security: - "/actuator/**" - "/loggers/**" - "/swagger-ui.html" + - "/swagger-ui/**" - "/swagger-resources/**" - - "/v2/api-docs" + - "/v3/api-docs" + - "/v3/**" - "/webjars/springfox-swagger-ui/**" - "/csrf" - "/error" diff --git a/src/test/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverterTest.java b/src/test/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverterTest.java index 3b73d19f5..fdb80ff43 100644 --- a/src/test/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverterTest.java +++ b/src/test/java/uk/gov/hmcts/reform/cwrdapi/oidc/JwtGrantedAuthoritiesConverterTest.java @@ -45,26 +45,26 @@ void test_shouldReturnEmptyAuthorities() { @Test void test_shouldReturnEmptyAuthoritiesWhenClaimNotAvailable() { - when(jwtMock.containsClaim(anyString())).thenReturn(false); + when(jwtMock.hasClaim(anyString())).thenReturn(false); Collection authorities = converter.convert(jwtMock); assertNotNull(authorities); assertEquals(0, authorities.size()); - verify(jwtMock, times(1)).containsClaim(anyString()); + verify(jwtMock, times(1)).hasClaim(anyString()); verify(idamRepositoryMock, times(0)).getUserInfo(anyString()); } @Test void test_shouldReturnEmptyAuthoritiesWhenClaimValueNotEquals() { - when(jwtMock.containsClaim(anyString())).thenReturn(true); + when(jwtMock.hasClaim(anyString())).thenReturn(true); when(jwtMock.getClaim(anyString())).thenReturn("Test"); Collection authorities = converter.convert(jwtMock); assertNotNull(authorities); assertEquals(0, authorities.size()); - verify(jwtMock, times(1)).containsClaim(anyString()); + verify(jwtMock, times(1)).hasClaim(anyString()); verify(jwtMock, times(1)).getClaim(anyString()); verify(idamRepositoryMock, times(0)).getUserInfo(anyString()); } @@ -73,7 +73,7 @@ void test_shouldReturnEmptyAuthoritiesWhenClaimValueNotEquals() { void test_shouldReturnEmptyAuthoritiesWhenIdamReturnsNoUsers() { List roles = new ArrayList<>(); - when(jwtMock.containsClaim(anyString())).thenReturn(true); + when(jwtMock.hasClaim(anyString())).thenReturn(true); when(jwtMock.getClaim(anyString())).thenReturn("access_token"); when(jwtMock.getTokenValue()).thenReturn("access_token"); when(userInfoMock.getRoles()).thenReturn(roles); @@ -83,7 +83,7 @@ void test_shouldReturnEmptyAuthoritiesWhenIdamReturnsNoUsers() { assertNotNull(authorities); assertEquals(0, authorities.size()); - verify(jwtMock, times(1)).containsClaim(anyString()); + verify(jwtMock, times(1)).hasClaim(anyString()); verify(jwtMock, times(1)).getClaim(anyString()); verify(jwtMock, times(1)).getTokenValue(); verify(userInfoMock, times(1)).getRoles(); @@ -95,7 +95,7 @@ void test_shouldReturnEmptyAuthoritiesWhenIdamReturnsNoUsers() { void test_shouldReturnEmptyAuthoritiesWhenIdamReturnsUsers() { List roles = new ArrayList<>(); roles.add("lrd-admin"); - when(jwtMock.containsClaim(anyString())).thenReturn(true); + when(jwtMock.hasClaim(anyString())).thenReturn(true); when(jwtMock.getClaim(anyString())).thenReturn("access_token"); when(jwtMock.getTokenValue()).thenReturn("access_token"); when(userInfoMock.getRoles()).thenReturn(roles); @@ -105,7 +105,7 @@ void test_shouldReturnEmptyAuthoritiesWhenIdamReturnsUsers() { assertNotNull(authorities); assertEquals(1, authorities.size()); - verify(jwtMock, times(1)).containsClaim(anyString()); + verify(jwtMock, times(1)).hasClaim(anyString()); verify(jwtMock, times(1)).getClaim(anyString()); verify(jwtMock, times(1)).getTokenValue(); verify(userInfoMock, times(1)).getRoles();