Skip to content

Commit

Permalink
[INJIWEB-665] : Error Handling in OVP Sharing (#363)
Browse files Browse the repository at this point in the history
* [INJIWEB-665] : Handling Errors for OVP Data Sharing

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : enable cross origin for presentation controller

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : enable cross origin for presentation controller

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : enable cross origin for presentation controller

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : handle the errors in mimoto through redirect

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : handle the errors in mimoto through redirect (#345)

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : handle the errors in mimoto through redirect

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : fixing the failed test

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : fixing the failed test

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : update injiweb url redirection

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : add missing tests for datashare impl

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : handle mosip vc long redirect uri error handling.

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : handle mosip vc long redirect uri error handling.

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : fix instance creation in datashare object

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : apply server properties to bootstrap

Signed-off-by: Vijay <[email protected]>

* [INJIWEB-665] : fix pr review comments.

Signed-off-by: Vijay <[email protected]>

---------

Signed-off-by: Vijay <[email protected]>
  • Loading branch information
vijay151096 committed Jul 30, 2024
1 parent b2321ec commit c67be19
Show file tree
Hide file tree
Showing 21 changed files with 364 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.mosip.mimoto.dto.ErrorDTO;
import io.mosip.mimoto.dto.idp.TokenResponseDTO;
import io.mosip.mimoto.exception.ApiNotAccessibleException;
import io.mosip.mimoto.exception.InvalidCredentialResourceException;
import io.mosip.mimoto.service.CredentialService;
import io.mosip.mimoto.service.IdpService;
import io.mosip.mimoto.service.IssuersService;
Expand Down Expand Up @@ -67,6 +68,10 @@ public ResponseEntity<?> downloadCredentialAsPDF(
logger.error("Exception occurred while fetching credential types ", exception);
responseWrapper.setErrors(List.of(new ErrorDTO(API_NOT_ACCESSIBLE_EXCEPTION.getCode(), API_NOT_ACCESSIBLE_EXCEPTION.getMessage())));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(responseWrapper);
} catch (InvalidCredentialResourceException invalidCredentialResourceException) {
logger.error("Exception occurred while pushing the data to data share ", invalidCredentialResourceException);
responseWrapper.setErrors(List.of(new ErrorDTO(invalidCredentialResourceException.getErrorCode(), invalidCredentialResourceException.getMessage())));
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(responseWrapper);
} catch (Exception exception) {
logger.error("Exception occurred while generating pdf ", exception);
responseWrapper.setErrors(List.of(new ErrorDTO(MIMOTO_PDF_SIGN_EXCEPTION.getCode(), exception.getMessage())));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,60 @@
package io.mosip.mimoto.controller;

import io.mosip.mimoto.dto.openid.presentation.PresentationRequestDTO;
import io.mosip.mimoto.exception.ApiNotAccessibleException;
import io.mosip.mimoto.exception.InvalidCredentialResourceException;
import io.mosip.mimoto.exception.InvalidVerifierException;
import io.mosip.mimoto.exception.ErrorConstants;
import io.mosip.mimoto.exception.VPNotCreatedException;
import io.mosip.mimoto.service.PresentationService;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@RestController
public class PresentationController {

@Autowired
PresentationService presentationService;

private final Logger logger = LoggerFactory.getLogger(PresentationController.class);

@Value("${mosip.inji.ovp.error.redirect.url}")
String injiOvpErrorRedirectUrl;

@Value("${mosip.inji.web.redirect.url}")
String injiWebRedirectUrl;

@GetMapping("/authorize")
public void performAuthorization(HttpServletResponse response, @ModelAttribute PresentationRequestDTO presentationRequestDTO) throws IOException, ApiNotAccessibleException {
public void performAuthorization(HttpServletResponse response, @ModelAttribute PresentationRequestDTO presentationRequestDTO) throws IOException {
try {
logger.info("Started Presentation Authorization in the controller.");
String redirectString = presentationService.authorizePresentation(presentationRequestDTO);
logger.info("Completed Presentation Authorization in the controller.");
response.sendRedirect(redirectString);
} catch (VPNotCreatedException | IOException | ApiNotAccessibleException exception){
logger.error("Exception Occurred in Authorizing the presentation" + exception);
throw exception;
} catch( InvalidVerifierException exception){
sendRedirect(response, injiWebRedirectUrl, exception.getErrorCode(), exception.getErrorText());
} catch(VPNotCreatedException | InvalidCredentialResourceException exception){
sendRedirect(response, presentationRequestDTO.getRedirect_uri(), exception.getErrorCode(), exception.getErrorText());
} catch (Exception exception){
sendRedirect(response, presentationRequestDTO.getRedirect_uri(), ErrorConstants.INTERNAL_SERVER_ERROR.getErrorCode(), ErrorConstants.INTERNAL_SERVER_ERROR.getErrorMessage());
}
}


private void sendRedirect(HttpServletResponse response, String domain, String code, String message) throws IOException {
logger.error("Exception Occurred in Authorizing the presentation");
String injiVerifyRedirectString = String.format(injiOvpErrorRedirectUrl,
domain,
code,
URLEncoder.encode(message, StandardCharsets.UTF_8));
response.setStatus(302);
response.sendRedirect(injiVerifyRedirectString);
}
}
4 changes: 3 additions & 1 deletion src/main/java/io/mosip/mimoto/dto/ErrorDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.fasterxml.jackson.annotation.JsonAlias;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

Expand All @@ -13,12 +14,13 @@
*
* @param errorcode the errorcode
* @param message the message
*
*
* @author Rishabh Keshari
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ErrorDTO implements Serializable {

private static final long serialVersionUID = 2452990684776944908L;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package io.mosip.mimoto.dto.openid.datashare;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DataShareResponseDTO {
private String url;
private int validForInMinutes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package io.mosip.mimoto.dto.openid.datashare;

import io.mosip.mimoto.dto.ErrorDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DataShareResponseWrapperDTO {
private String id;
private String version;
private String responsetime;
@NotNull
private DataShareResponseDTO dataShare;

private List<ErrorDTO> errors = new ArrayList<>();
}
24 changes: 24 additions & 0 deletions src/main/java/io/mosip/mimoto/exception/ErrorConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.mosip.mimoto.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ErrorConstants {

INVALID_REQUEST("invalid_request", "Some incorrect parameters in the request"),
UNSUPPORTED_FORMAT("unsupported_format", "No VC of this format is found"),
RESOURCE_NOT_FOUND("resource_not_found", "The requested resource doesn’t exist."),
SERVER_UNAVAILABLE("server_unavailable", "The server is not reachable right now."),
RESOURCE_EXPIRED("resource_expired", "The requested resource expired."),
REQUEST_TIMED_OUT("request_timed_out", "We are unable to process your request right now"),
URI_TOO_LONG("uri_too_long", "Resource URI is too long to be handled"),
INVALID_CLIENT("invalid_client", "The requested client doesn’t match."),
INVALID_REDIRECT_URI("invalid_redirect_uri", "The requested redirect uri doesn’t match."),
INTERNAL_SERVER_ERROR("internal_server_error", "We are unable to process request now");

private final String errorCode;
private final String errorMessage;

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public InvalidCredentialResourceException(String errorCode, String errorMessage)
}

public InvalidCredentialResourceException(String errorMessage) {
super(PlatformErrorMessages.MIMOTO_PGS_INVALID_INPUT_PARAMETER.getCode(), errorMessage);
super(ErrorConstants.RESOURCE_NOT_FOUND.getErrorCode(), errorMessage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ public enum PlatformErrorMessages {
MIMOTO_ISSUER_ONBOARDING_EXCEPTION(PlatformConstants.PREFIX + "037", "Issuers Onboarding exception occurred "),
INVALID_VERIFIER_ID_EXCEPTION(PlatformConstants.PREFIX + "038", "Invalid Verifier ClientId"),
INVALID_VERIFIER_REDIRECT_URI_EXCEPTION(PlatformConstants.PREFIX + "039", "Invalid Redirect Uri"),
NO_CREDENTIALS_MATCH_VP_DEFINITION_EXCEPTION(PlatformConstants.PREFIX + "040", "VP Request Results Empty Credentials"),
INVALID_CREDENTIAL_RESOURCE_URI_EXCEPTION(PlatformConstants.PREFIX + "041", "The Credential Resource is Invalid");
INVALID_CREDENTIAL_RESOURCE_URI_EXCEPTION(PlatformConstants.PREFIX + "040", "The Credential Resource is Invalid");

/** The error message. */
private final String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public VPNotCreatedException(String errorCode, String errorMessage) {
}

public VPNotCreatedException(String errorMessage) {
super(PlatformErrorMessages.NO_CREDENTIALS_MATCH_VP_DEFINITION_EXCEPTION.getCode(), errorMessage);
super(ErrorConstants.INVALID_REQUEST.getErrorCode(), errorMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package io.mosip.mimoto.service;

import io.mosip.mimoto.dto.openid.VerifierDTO;
import io.mosip.mimoto.dto.openid.VerifiersDTO;
import io.mosip.mimoto.dto.openid.presentation.PresentationRequestDTO;
import io.mosip.mimoto.exception.ApiNotAccessibleException;

import java.io.IOException;
import java.util.Optional;

public interface VerifiersService {
Optional<VerifierDTO> getVerifiersByClientId(String clientId) throws ApiNotAccessibleException, IOException;
public interface VerifierService {
Optional<VerifierDTO> getVerifierByClientId(String clientId) throws ApiNotAccessibleException, IOException;
void validateVerifier(PresentationRequestDTO presentationRequestDTO) throws ApiNotAccessibleException, IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
import io.mosip.mimoto.dto.IssuersDTO;
import io.mosip.mimoto.dto.idp.TokenResponseDTO;
import io.mosip.mimoto.dto.mimoto.*;
import io.mosip.mimoto.dto.openid.presentation.Format;
import io.mosip.mimoto.dto.openid.presentation.InputDescriptorDTO;
import io.mosip.mimoto.dto.openid.presentation.LDPVc;
import io.mosip.mimoto.dto.openid.presentation.PresentationDefinitionDTO;
import io.mosip.mimoto.exception.ApiNotAccessibleException;
import io.mosip.mimoto.exception.IdpException;
import io.mosip.mimoto.exception.InvalidCredentialResourceException;
import io.mosip.mimoto.exception.ErrorConstants;
import io.mosip.mimoto.service.CredentialService;
import io.mosip.mimoto.service.IdpService;
import io.mosip.mimoto.service.IssuersService;
Expand All @@ -31,7 +30,6 @@
import io.mosip.mimoto.util.Utilities;
import io.mosip.pixelpass.PixelPass;
import org.apache.commons.lang.StringUtils;
import org.apache.http.auth.InvalidCredentialsException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.jetbrains.annotations.NotNull;
Expand All @@ -54,8 +52,6 @@
import java.util.*;
import java.util.stream.Collectors;

import static io.mosip.mimoto.exception.PlatformErrorMessages.INVALID_CREDENTIAL_TYPE_EXCEPTION;

@Service
public class CredentialServiceImpl implements CredentialService {

Expand Down Expand Up @@ -111,7 +107,7 @@ public ByteArrayInputStream downloadCredentialAsPDF(String issuerId, String cred
return generatePdfForVerifiableCredentials(vcCredentialResponse, issuerConfig, credentialsSupportedResponseDraft11, dataShareUrl);
}

public VCCredentialResponse downloadCredential(String credentialEndpoint, VCCredentialRequest vcCredentialRequest, String accessToken) throws ApiNotAccessibleException, IOException, InvalidCredentialsException {
public VCCredentialResponse downloadCredential(String credentialEndpoint, VCCredentialRequest vcCredentialRequest, String accessToken) throws InvalidCredentialResourceException {
VCCredentialResponse vcCredentialResponse = restApiClient.postApi(credentialEndpoint, MediaType.APPLICATION_JSON,
vcCredentialRequest, VCCredentialResponse.class, accessToken);
logger.debug("VC Credential Response is -> " + vcCredentialResponse);
Expand Down Expand Up @@ -312,13 +308,13 @@ public CredentialIssuerWellKnownResponseDraft11 getCredentialIssuerWellknown(Str
return credentialIssuerWellKnownResponseDraft11;
}

public CredentialsSupportedResponseDraft11 getCredentialSupported(CredentialIssuerWellKnownResponseDraft11 credentialIssuerWellKnownResponseDraft11, String credentialType) throws ApiNotAccessibleException, IOException, InvalidCredentialsException {
public CredentialsSupportedResponseDraft11 getCredentialSupported(CredentialIssuerWellKnownResponseDraft11 credentialIssuerWellKnownResponseDraft11, String credentialType) throws InvalidCredentialResourceException {
Optional<CredentialsSupportedResponseDraft11> credentialsSupportedResponse = credentialIssuerWellKnownResponseDraft11.getCredentialsSupported().stream()
.filter(credentialsSupported -> credentialsSupported.getId().equals(credentialType))
.findFirst();
if (credentialsSupportedResponse.isEmpty()){
logger.error("Invalid credential Type passed - {}", credentialType);
throw new InvalidCredentialsException(INVALID_CREDENTIAL_TYPE_EXCEPTION.getMessage());
throw new InvalidCredentialResourceException(ErrorConstants.RESOURCE_NOT_FOUND.getErrorMessage());
}
return credentialsSupportedResponse.get();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package io.mosip.mimoto.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.mosip.mimoto.dto.mimoto.VCCredentialResponse;
import io.mosip.mimoto.dto.openid.datashare.DataShareResponseWrapperDTO;
import io.mosip.mimoto.dto.openid.presentation.PresentationRequestDTO;
import io.mosip.mimoto.exception.InvalidCredentialResourceException;
import io.mosip.mimoto.exception.ErrorConstants;
import io.mosip.mimoto.util.RestApiClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
Expand All @@ -19,11 +27,19 @@ public class DataShareServiceImpl {
@Autowired
RestApiClient restApiClient;

@Value("${public.url}")
String publicHostUrl;
@Value("${mosip.data.share.host}")
String dataShareHostUrl;

@Value("${mosip.data.share.url}")
String dataShareUrl;
@Value("${mosip.data.share.create.url}")
String dataShareCreateUrl;

@Value("${mosip.data.share.create.retry.count}")
Integer maxRetryCount;

private final Logger logger = LoggerFactory.getLogger(DataShareServiceImpl.class);

@Autowired
ObjectMapper objectMapper;

public String storeDataInDataShare(String data) throws Exception {
ByteArrayResource contentsAsResource = new ByteArrayResource(data.getBytes()) {
Expand All @@ -38,10 +54,43 @@ public String getFilename() {
headers.setContentType(MediaType.MULTIPART_FORM_DATA);

HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
DataShareResponseWrapperDTO dataShareResponseWrapperDTO = restApiClient.postApi(dataShareUrl, MediaType.MULTIPART_FORM_DATA, requestEntity, DataShareResponseWrapperDTO.class);
DataShareResponseWrapperDTO dataShareResponseWrapperDTO = pushCredentialIntoDataShare(requestEntity);
URL dataShareUrl = new URL(dataShareResponseWrapperDTO.getDataShare().getUrl());
// return publicHostUrl + dataShareUrl.getPath();
return "https://api-internal.dev.mosip.net" + dataShareUrl.getPath();
return dataShareHostUrl + dataShareUrl.getPath();
}

private DataShareResponseWrapperDTO pushCredentialIntoDataShare(HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity) throws Exception {
int attempt =0 ;
DataShareResponseWrapperDTO dataShareResponseWrapperDTO = null;
while(attempt++ < maxRetryCount ){
try {
dataShareResponseWrapperDTO = restApiClient.postApi(dataShareCreateUrl, MediaType.MULTIPART_FORM_DATA, requestEntity, DataShareResponseWrapperDTO.class);
} catch (Exception e) {
logger.error(attempt + " attempt to push credential failed");
}
}
if(dataShareResponseWrapperDTO == null){
throw new InvalidCredentialResourceException(
ErrorConstants.REQUEST_TIMED_OUT.getErrorCode(),
ErrorConstants.REQUEST_TIMED_OUT.getErrorMessage());
}
return dataShareResponseWrapperDTO;
}

public VCCredentialResponse downloadCredentialFromDataShare(PresentationRequestDTO presentationRequestDTO) throws JsonProcessingException {
logger.info("Started the Credential Download From DataShare");
String credentialsResourceUri = presentationRequestDTO.getResource();
String vcCredentialResponseString = restApiClient.getApi(credentialsResourceUri, String.class);
if (vcCredentialResponseString == null) {
throw new InvalidCredentialResourceException(
ErrorConstants.SERVER_UNAVAILABLE.getErrorCode(),
ErrorConstants.SERVER_UNAVAILABLE.getErrorMessage());
}
VCCredentialResponse vcCredentialResponse = objectMapper.readValue(vcCredentialResponseString, VCCredentialResponse.class);
if(vcCredentialResponse.getCredential() == null){
throw new InvalidCredentialResourceException(ErrorConstants.RESOURCE_EXPIRED.getErrorMessage());
}
return vcCredentialResponse;
}

}
Loading

0 comments on commit c67be19

Please sign in to comment.