Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SELC-4591] Feat: Added V2 API for retrieve back-office URI #391

Merged
merged 8 commits into from
Apr 2, 2024
92 changes: 92 additions & 0 deletions app/src/main/resources/swagger/api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2265,6 +2265,98 @@
} ]
}
},
"/v2/products/{productId}/back-office" : {
"get" : {
"tags" : [ "products" ],
"summary" : "retrieveProductBackoffice",
"description" : "Service to trigger token exchange and redirect to product's back office URL",
"operationId" : "retrieveProductBackofficeUsingGET_1",
"parameters" : [ {
"name" : "productId",
"in" : "path",
"description" : "Product's unique identifier",
"required" : true,
"style" : "simple",
"schema" : {
"type" : "string"
}
}, {
"name" : "institutionId",
"in" : "query",
"description" : "Institution's unique internal identifier",
"required" : true,
"style" : "form",
"schema" : {
"type" : "string"
}
}, {
"name" : "environment",
"in" : "query",
"description" : "Back Office environment",
"required" : false,
"style" : "form",
"schema" : {
"type" : "string"
}
} ],
"responses" : {
"200" : {
"description" : "OK",
"content" : {
"application/json" : {
"schema" : {
"type" : "string",
"format" : "uri"
}
}
}
},
"400" : {
"description" : "Bad Request",
"content" : {
"application/problem+json" : {
"schema" : {
"$ref" : "#/components/schemas/Problem"
}
}
}
},
"401" : {
"description" : "Unauthorized",
"content" : {
"application/problem+json" : {
"schema" : {
"$ref" : "#/components/schemas/Problem"
}
}
}
},
"404" : {
"description" : "Not Found",
"content" : {
"application/problem+json" : {
"schema" : {
"$ref" : "#/components/schemas/Problem"
}
}
}
},
"500" : {
"description" : "Internal Server Error",
"content" : {
"application/problem+json" : {
"schema" : {
"$ref" : "#/components/schemas/Problem"
}
}
}
}
},
"security" : [ {
"bearerAuth" : [ "global" ]
} ]
}
},
"/v1/relationships/{relationshipId}" : {
"delete" : {
"tags" : [ "relationships" ],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ public UserInstitution getProducts(String institutionId, String userId) {
userId
).getBody();

if (Objects.isNull(institutionResponses) || institutionResponses.size() != 1)

if (CollectionUtils.isEmpty(institutionResponses) || institutionResponses.size() != 1){
throw new ResourceNotFoundException(String.format("InstitutionId %s and userId %s not found", institutionId, userId));
}

log.debug("getProducts result = {}", institutionResponses);
log.trace("getProducts end");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package it.pagopa.selfcare.dashboard.web.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import it.pagopa.selfcare.dashboard.web.model.ExchangedToken;
import it.pagopa.selfcare.dashboard.web.security.ExchangeTokenServiceV2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping(value = "/v2/products", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = "products")
public class ProductV2Controller {

private final ExchangeTokenServiceV2 exchangeTokenService;

@Autowired
public ProductV2Controller(ExchangeTokenServiceV2 exchangeTokenServiceV2) {
this.exchangeTokenService = exchangeTokenServiceV2;
}

@GetMapping(value = "/{productId}/back-office")
@ResponseStatus(HttpStatus.OK)
@ApiOperation(value = "${swagger.dashboard.product.api.retrieveProductBackoffice}", notes = "${swagger.dashboard.product.api.retrieveProductBackoffice}", nickname = "v2RetrieveProductBackofficeUsingGET")
@PreAuthorize("hasPermission(new it.pagopa.selfcare.dashboard.web.security.ProductAclDomain(#institutionId, #productId), 'ANY')")
public URI retrieveProductBackoffice(@ApiParam("${swagger.dashboard.products.model.id}")
@PathVariable("productId")
String productId,
@ApiParam("${swagger.dashboard.institutions.model.id}")
@RequestParam("institutionId")
String institutionId,
@ApiParam("${swagger.dashboard.product-backoffice-configurations.model.environment}")
@RequestParam(value = "environment", required = false)
Optional<String> environment) {
log.trace("accessProductBackoffice start");
log.debug("accessProductBackoffice institutionId = {}, productId = {}", institutionId, productId);
final ExchangedToken exchangedToken = exchangeTokenService.exchange(institutionId, productId, environment);
final URI location = URI.create(exchangedToken.getBackOfficeUrl().replace("<IdentityToken>", exchangedToken.getIdentityToken()));
log.trace("accessProductBackoffice end");
return location;

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package it.pagopa.selfcare.dashboard.web.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import it.pagopa.selfcare.dashboard.core.ProductService;
import it.pagopa.selfcare.dashboard.web.config.WebTestConfig;
import it.pagopa.selfcare.dashboard.web.model.ExchangedToken;
import it.pagopa.selfcare.dashboard.web.model.mapper.BrokerResourceMapperImpl;
import it.pagopa.selfcare.dashboard.web.security.ExchangeTokenServiceV2;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.net.URI;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(value = {ProductV2Controller.class}, excludeAutoConfiguration = SecurityAutoConfiguration.class)
@ContextConfiguration(classes = {ProductV2Controller.class, WebTestConfig.class, BrokerResourceMapperImpl.class})
class ProductV2ControllerTest {
private static final String BASE_URL = "/v2/products";

@Autowired
protected MockMvc mvc;

@Autowired
protected ObjectMapper objectMapper;

@MockBean
private ProductService productServiceMock;

@MockBean
private ExchangeTokenServiceV2 exchangeTokenServiceMock;

@Test
void retrieveProductBackoffice() throws Exception {
// given
String productId = "prod1";
String institutionId = "inst1";
final String identityToken = "identityToken";
final String backOfficeUrl = "back-office-url#token=";
when(exchangeTokenServiceMock.exchange(any(), any(), any()))
.thenReturn(new ExchangedToken(identityToken, backOfficeUrl + "<IdentityToken>"));
// when
MvcResult result = mvc.perform(MockMvcRequestBuilders
.get(BASE_URL + "/{productId}/back-office", productId)
.queryParam("institutionId", institutionId)
.contentType(APPLICATION_JSON_VALUE)
.accept(APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andReturn();
// then
URI response = objectMapper.readValue(result.getResponse().getContentAsString(), URI.class);
assertTrue(response.toString().contains(identityToken));
assertTrue(response.toString().contains(backOfficeUrl));

verify(exchangeTokenServiceMock, times(1))
.exchange(institutionId, productId, Optional.empty());
verifyNoMoreInteractions(exchangeTokenServiceMock);
verifyNoInteractions(productServiceMock);
}

}