diff --git a/.github/workflows/push-trigger.yml b/.github/workflows/push-trigger.yml index e773309f..7606b056 100644 --- a/.github/workflows/push-trigger.yml +++ b/.github/workflows/push-trigger.yml @@ -44,7 +44,7 @@ jobs: secrets: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} - OSSRH_URL: ${{ secrets.OSSRH_SNAPSHOT_URL }} + OSSRH_URL: ${{ secrets.OSSRH_CENTRAL_URL }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} GPG_SECRET: ${{ secrets.GPG_SECRET }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} @@ -85,7 +85,7 @@ jobs: secrets: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} - OSSRH_URL: ${{ secrets.OSSRH_SNAPSHOT_URL }} + OSSRH_URL: ${{ secrets.OSSRH_CENTRAL_URL }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} GPG_SECRET: ${{ secrets.GPG_SECRET }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} @@ -126,7 +126,7 @@ jobs: secrets: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} - OSSRH_URL: ${{ secrets.OSSRH_SNAPSHOT_URL }} + OSSRH_URL: ${{ secrets.OSSRH_CENTRAL_URL }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} GPG_SECRET: ${{ secrets.GPG_SECRET }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} @@ -167,7 +167,7 @@ jobs: secrets: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} - OSSRH_URL: ${{ secrets.OSSRH_SNAPSHOT_URL }} + OSSRH_URL: ${{ secrets.OSSRH_CENTRAL_URL }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} GPG_SECRET: ${{ secrets.GPG_SECRET }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} @@ -208,7 +208,7 @@ jobs: secrets: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }} - OSSRH_URL: ${{ secrets.OSSRH_SNAPSHOT_URL }} + OSSRH_URL: ${{ secrets.OSSRH_CENTRAL_URL }} OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }} GPG_SECRET: ${{ secrets.GPG_SECRET }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} diff --git a/mock-certify-plugin/pom.xml b/mock-certify-plugin/pom.xml index 7c97c7aa..86f697de 100644 --- a/mock-certify-plugin/pom.xml +++ b/mock-certify-plugin/pom.xml @@ -8,14 +8,14 @@ 4.0.0 - io.mosip.certify + io.inji.certify mock-certify-plugin - 0.4.0-SNAPSHOT + 0.6.0-SNAPSHOT jar mock-certify-integration-impl Mockup of a wrapper implementation that is used to showcase the integration with certify - https://github.com/mosip/digital-credential-plugins + https://github.com/inji/digital-credential-plugins @@ -24,17 +24,17 @@ - scm:git:git://github.com/mosip/digital-credential-plugins.git - scm:git:ssh://github.com:mosip/digital-credential-plugins.git - https://github.com/mosip/digital-credential-plugins + scm:git:git://github.com/inji/digital-credential-plugins.git + scm:git:ssh://github.com:inji/digital-credential-plugins.git + https://github.com/inji/digital-credential-plugins HEAD Mosip mosip.emailnotifier@gmail.com - io.mosip - https://www.mosip.io + io.inji + https://inji.io @@ -48,7 +48,7 @@ 3.2.5 1.5 2.2.1 - 6.1.0 + 0.7.0 3.0.1 0.8.11 3.6.3 @@ -63,15 +63,15 @@ provided - io.mosip.certify + io.inji.certify certify-core - 0.11.0-SNAPSHOT + 0.14.0-SNAPSHOT provided io.mosip.esignet esignet-core - 1.5.1 + 1.6.2 * @@ -82,7 +82,7 @@ io.mosip.esignet esignet-integration-api - 1.5.1 + 1.6.2 * @@ -170,9 +170,9 @@ - ossrh - CentralRepository - https://oss.sonatype.org/content/repositories/snapshots + ossrh-central + MavenCentralRepository + https://central.sonatype.com/repository/maven-snapshots default true @@ -200,14 +200,13 @@ ossrh - https://oss.sonatype.org/content/repositories/snapshots + https://central.sonatype.com/repository/maven-snapshots/ ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://central.sonatype.com/api/v1/publisher - @@ -262,26 +261,15 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.14 + org.sonatype.central + central-publishing-maven-plugin + ${central.publishing.maven.plugin.version} true - - - default-deploy - deploy - - deploy - - - - ossrh - https://oss.sonatype.org/ - false + ossrh + false - org.apache.maven.plugins maven-source-plugin diff --git a/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java b/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java index d5542f9b..500fb411 100644 --- a/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java +++ b/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java @@ -62,6 +62,9 @@ public class MDocMockVCIssuancePlugin implements VCIssuancePlugin { private static final String ACCESS_TOKEN_HASH = "accessTokenHash"; public static final String CERTIFY_SERVICE_APP_ID = "CERTIFY_SERVICE"; + + @Autowired + private MdocGenerator mdocGenerator; @Override public VCResult getVerifiableCredentialWithLinkedDataProof(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { @@ -84,7 +87,7 @@ public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, Strin VCResult vcResult = new VCResult<>(); String mdocVc; try { - mdocVc = new MdocGenerator().generate(mockDataForMsoMdoc(documentNumber),holderId, issuerKeyAndCertificate); + mdocVc = mdocGenerator.generate(mockDataForMsoMdoc(documentNumber),holderId, issuerKeyAndCertificate); } catch (Exception e) { log.error("Exception on mdoc creation", e); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); diff --git a/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java b/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java new file mode 100644 index 00000000..31f29d5a --- /dev/null +++ b/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java @@ -0,0 +1,173 @@ +package io.mosip.certify.mock.integration.service; + +import io.mosip.certify.api.dto.VCRequestDto; +import io.mosip.certify.api.dto.VCResult; +import io.mosip.certify.api.exception.VCIExchangeException; +import io.mosip.certify.constants.VCFormats; +import io.mosip.certify.core.exception.CertifyException; +import io.mosip.certify.mock.integration.mocks.MdocGenerator; +import io.mosip.esignet.core.dto.OIDCTransaction; +import io.mosip.kernel.core.keymanager.spi.KeyStore; +import io.mosip.kernel.keymanagerservice.entity.KeyAlias; +import io.mosip.kernel.keymanagerservice.helper.KeymanagerDBHelper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.*; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.test.util.ReflectionTestUtils; + +import java.security.Key; +import java.time.LocalDateTime; +import java.util.*; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +@RunWith(org.mockito.junit.MockitoJUnitRunner.class) +public class MDocMockVCIssuancePluginTest { + + @InjectMocks + private MDocMockVCIssuancePlugin plugin; + + @Mock + private CacheManager cacheManager; + @Mock + private KeyStore keyStore; + @Mock + private KeymanagerDBHelper dbHelper; + @Mock + private Cache cache; + @Mock + private Key key; + @Mock + private MdocGenerator mdocGenerator; + + @Before + public void setUp() { + ReflectionTestUtils.setField(plugin, "issuerKeyAndCertificate", "empty"); + ReflectionTestUtils.setField(plugin, "cacheSecretKeyRefId", "refId"); + ReflectionTestUtils.setField(plugin, "aesECBTransformation", "AES/ECB/PKCS5Padding"); + ReflectionTestUtils.setField(plugin, "storeIndividualId", true); + ReflectionTestUtils.setField(plugin, "secureIndividualId", false); + } + + @Test + public void testGetVerifiableCredential_Success() throws Exception { + VCRequestDto dto = mock(VCRequestDto.class); + when(dto.getFormat()).thenReturn(VCFormats.MSO_MDOC); + + Map identityDetails = new HashMap<>(); + identityDetails.put("accessTokenHash", "tokenHash"); + + OIDCTransaction transaction = mock(OIDCTransaction.class); + when(transaction.getIndividualId()).thenReturn("docNum"); + + when(cacheManager.getCache(anyString())).thenReturn(cache); + when(cache.get(anyString(), eq(OIDCTransaction.class))).thenReturn(transaction); + + when(mdocGenerator.generate(anyMap(), anyString(), anyString())).thenReturn("mockedMdoc"); + + VCResult result = plugin.getVerifiableCredential(dto, "holderId", identityDetails); + + assertNotNull(result); + assertEquals(VCFormats.MSO_MDOC, result.getFormat()); + assertEquals("mockedMdoc", result.getCredential()); + } + + @Test(expected = VCIExchangeException.class) + public void testGetVerifiableCredential_NotImplemented() throws Exception { + VCRequestDto dto = mock(VCRequestDto.class); + + Map identityDetails = new HashMap<>(); + identityDetails.put("accessTokenHash", "tokenHash"); + + plugin.getVerifiableCredential(dto, "holderId", identityDetails); + } + + @Test(expected = VCIExchangeException.class) + public void testGetVerifiableCredentialWithLinkedDataProof_NotImplemented() throws Exception { + VCRequestDto dto = mock(VCRequestDto.class); + plugin.getVerifiableCredentialWithLinkedDataProof(dto, "holderId", new HashMap<>()); + } + + @Test + public void testGetIndividualId_SecureFalse() { + OIDCTransaction transaction = mock(OIDCTransaction.class); + when(transaction.getIndividualId()).thenReturn("docNum"); + ReflectionTestUtils.setField(plugin, "secureIndividualId", false); + ReflectionTestUtils.setField(plugin, "storeIndividualId", true); + String result = (String) ReflectionTestUtils.invokeMethod(plugin, "getIndividualId", transaction); + assertEquals("docNum", result); + } + + @Test + public void testGetIndividualId_StoreFalse() { + OIDCTransaction transaction = mock(OIDCTransaction.class); + ReflectionTestUtils.setField(plugin, "storeIndividualId", false); + String result = (String) ReflectionTestUtils.invokeMethod(plugin, "getIndividualId", transaction); + assertNull(result); + } + + @Test(expected = CertifyException.class) + public void testDecryptIndividualId_Exception() { + ReflectionTestUtils.setField(plugin, "aesECBTransformation", "invalid"); + ReflectionTestUtils.invokeMethod(plugin, "decryptIndividualId", "invalid"); + } + + @Test(expected = CertifyException.class) + public void testGetSecretKeyFromHSM_NoAlias() { + when(dbHelper.getKeyAliases(anyString(), anyString(), any(LocalDateTime.class))) + .thenReturn(Collections.singletonMap("currentKeyAlias", new ArrayList<>())); + ReflectionTestUtils.invokeMethod(plugin, "getSecretKeyFromHSM"); + } + + @Test + public void testGetKeyAlias_Success() { + KeyAlias alias = mock(KeyAlias.class); + when(alias.getAlias()).thenReturn("alias"); + List aliases = Collections.singletonList(alias); + Map> map = new HashMap<>(); + map.put("currentKeyAlias", aliases); + when(dbHelper.getKeyAliases(anyString(), anyString(), any(LocalDateTime.class))).thenReturn(map); + String result = (String) ReflectionTestUtils.invokeMethod(plugin, "getKeyAlias", "appId", "refId"); + assertEquals("alias", result); + } + + @Test(expected = CertifyException.class) + public void testGetKeyAlias_NotUnique() { + List aliases = Arrays.asList(mock(KeyAlias.class), mock(KeyAlias.class)); + Map> map = new HashMap<>(); + map.put("currentKeyAlias", aliases); + when(dbHelper.getKeyAliases(anyString(), anyString(), any(LocalDateTime.class))).thenReturn(map); + ReflectionTestUtils.invokeMethod(plugin, "getKeyAlias", "appId", "refId"); + } + + @Test + public void testMockDataForMsoMdoc() { + String docNum = "12345"; + @SuppressWarnings("unchecked") + Map data = (Map) ReflectionTestUtils.invokeMethod(plugin, "mockDataForMsoMdoc", docNum); + assertNotNull(data); + assertEquals("Agatha", data.get("family_name")); + assertEquals("Joseph", data.get("given_name")); + assertEquals("1994-11-06", data.get("birth_date")); + assertEquals("IN", data.get("issuing_country")); + assertEquals(docNum, data.get("document_number")); + assertTrue(data.get("driving_privileges") instanceof Map); + assertEquals("A", ((Map) data.get("driving_privileges")).get("vehicle_category_code")); + } + + @Test + public void testGetUserInfoTransaction() { + String accessTokenHash = "tokenHash"; + OIDCTransaction transaction = mock(OIDCTransaction.class); + when(cacheManager.getCache(anyString())).thenReturn(cache); + when(cache.get(eq(accessTokenHash), eq(OIDCTransaction.class))).thenReturn(transaction); + + OIDCTransaction result = (OIDCTransaction) ReflectionTestUtils.invokeMethod(plugin, "getUserInfoTransaction", accessTokenHash); + assertNotNull(result); + assertEquals(transaction, result); + } +} \ No newline at end of file diff --git a/mosip-identity-certify-plugin/pom.xml b/mosip-identity-certify-plugin/pom.xml index 8bb0b39d..5ba256ee 100644 --- a/mosip-identity-certify-plugin/pom.xml +++ b/mosip-identity-certify-plugin/pom.xml @@ -6,14 +6,14 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.mosip.certify + io.inji.certify mosip-identity-certify-plugin - 0.4.0-SNAPSHOT + 0.6.0-SNAPSHOT jar mosipid-certify-integration-impl MOSIP-ID plugin implementation that is used for the integration with certify - https://github.com/mosip/digital-credential-plugins + https://github.com/inji/digital-credential-plugins @@ -22,25 +22,25 @@ - scm:git:git://github.com/mosip/digital-credential-plugins.git - scm:git:ssh://github.com:mosip/digital-credential-plugins.git - https://github.com/mosip/digital-credential-plugins + scm:git:git://github.com/inji/digital-credential-plugins.git + scm:git:ssh://github.com:inji/digital-credential-plugins.git + https://github.com/inji/digital-credential-plugins HEAD Mosip mosip.emailnotifier@gmail.com - io.mosip - https://www.mosip.io + io.inji + https://inji.io - ossrh - CentralRepository - https://oss.sonatype.org/content/repositories/snapshots + ossrh-central + MavenCentralRepository + https://central.sonatype.com/repository/maven-snapshots default true @@ -64,14 +64,13 @@ ossrh - https://oss.sonatype.org/content/repositories/snapshots + https://central.sonatype.com/repository/maven-snapshots/ ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://central.sonatype.com/api/v1/publisher - 21 21 @@ -85,6 +84,7 @@ 3.6.3 1.3.0-beta.1 2.12.1 + 0.7.0 @@ -96,15 +96,15 @@ provided - io.mosip.certify + io.inji.certify certify-core - 0.11.0-SNAPSHOT + 0.14.0-SNAPSHOT provided - io.mosip.certify + io.inji.certify certify-integration-api - 0.11.0-SNAPSHOT + 0.14.0-SNAPSHOT provided @@ -146,7 +146,7 @@ io.mosip.esignet esignet-core - 1.5.1 + 1.6.2 * @@ -157,7 +157,7 @@ io.mosip.esignet esignet-integration-api - 1.5.1 + 1.6.2 * @@ -165,6 +165,11 @@ + + com.fasterxml.jackson.core + jackson-annotations + 2.15.4 + @@ -221,23 +226,13 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.14 + org.sonatype.central + central-publishing-maven-plugin + ${central.publishing.maven.plugin.version} true - - - default-deploy - deploy - - deploy - - - - ossrh - https://oss.sonatype.org/ - false + ossrh + false diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/dto/IdaKycExchangeRequest.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/dto/IdaKycExchangeRequest.java new file mode 100644 index 00000000..0c1a2339 --- /dev/null +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/dto/IdaKycExchangeRequest.java @@ -0,0 +1,41 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.certify.mosipid.integration.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class IdaKycExchangeRequest { + + private String id; + private String version; + private String requestTime; + private String transactionID; + private String kycToken; + private List consentObtained; + private List locales; + private String respType; + private String individualId; + + /** + * claims metadata - Not set/un used for now from IDA + */ + private Map metadata; + /** + * User consented verified claims list. + */ + List> verifiedConsentedClaims; + /** + * User consented unverified claims list. + */ + Map unVerifiedConsentedClaims; + +} diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/dto/IdaKycExchangeResponse.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/dto/IdaKycExchangeResponse.java new file mode 100644 index 00000000..f2cb273d --- /dev/null +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/dto/IdaKycExchangeResponse.java @@ -0,0 +1,14 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.certify.mosipid.integration.dto; + +import lombok.Data; + +@Data +public class IdaKycExchangeResponse { + + private String encryptedKyc; +} diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/AuthTransactionHelper.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/AuthTransactionHelper.java index fde6367f..ef9ce498 100644 --- a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/AuthTransactionHelper.java +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/AuthTransactionHelper.java @@ -27,7 +27,7 @@ @Component @Slf4j -@ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "IdaVCIssuancePluginImpl") +@ConditionalOnProperty(value = "mosip.certify.integration.data-provider-plugin", havingValue = "IdaDataProviderPluginImpl") public class AuthTransactionHelper { private static final String AUTH_TOKEN_CACHE = "authtokens"; diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/TransactionHelper.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/TransactionHelper.java new file mode 100644 index 00000000..a6e8928a --- /dev/null +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/TransactionHelper.java @@ -0,0 +1,33 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.certify.mosipid.integration.helper; + +import io.mosip.esignet.core.dto.OIDCTransaction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Component; + +@Component +@ConditionalOnProperty(value = "mosip.certify.integration.data-provider-plugin", havingValue = "IdaDataProviderPluginImpl") +public class TransactionHelper { + + @Autowired + CacheManager cacheManager; + + @Value("${mosip.certify.ida.vci-user-info-cache}") + private String userinfoCache; + + @SuppressWarnings("unchecked") + public OIDCTransaction getOAuthTransaction(String accessTokenHash) throws Exception { + if (cacheManager.getCache(userinfoCache) != null) { + return cacheManager.getCache(userinfoCache).get(accessTokenHash, OIDCTransaction.class); //NOSONAR getCache() will not be returning null here. + } + throw new Exception("cache_missing"); + } + +} diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCIAuthTransactionHelper.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCIAuthTransactionHelper.java new file mode 100644 index 00000000..ed7cfb98 --- /dev/null +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCIAuthTransactionHelper.java @@ -0,0 +1,81 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.certify.mosipid.integration.helper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.certify.mosipid.integration.dto.ClientIdSecretKeyRequest; +import io.mosip.kernel.core.http.RequestWrapper; +import io.mosip.kernel.core.http.ResponseWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import java.time.LocalDateTime; + +@Component +@Slf4j +@ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "IdaVCIssuancePluginImpl") +@Deprecated +public class VCIAuthTransactionHelper { + + private static final String AUTH_TOKEN_CACHE = "authtokens"; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private RestTemplate restTemplate; + + @Value("${mosip.certify.authenticator.ida.auth-token-url}") + private String authTokenUrl; + + @Value("${mosip.certify.authenticator.ida.client-id}") + private String clientId; + + @Value("${mosip.certify.authenticator.ida.secret-key}") + private String secretKey; + + @Value("${mosip.certify.authenticator.ida.app-id}") + private String appId; + + @Cacheable(value = AUTH_TOKEN_CACHE, key = "#root.target.AUTH_TOKEN_CACHE_KEY") + public String getAuthToken() throws Exception { + log.info("Started to get auth-token with appId : {} && clientId : {}", + appId, clientId); + + RequestWrapper authRequest = new RequestWrapper<>(); + authRequest.setRequesttime(LocalDateTime.now()); + ClientIdSecretKeyRequest clientIdSecretKeyRequest = new ClientIdSecretKeyRequest(clientId, secretKey, appId); + authRequest.setRequest(clientIdSecretKeyRequest); + + String requestBody = objectMapper.writeValueAsString(authRequest); + RequestEntity requestEntity = RequestEntity + .post(UriComponentsBuilder.fromUriString(authTokenUrl).build().toUri()) + .contentType(MediaType.APPLICATION_JSON) + .body(requestBody); + ResponseEntity responseEntity = restTemplate.exchange(requestEntity, + new ParameterizedTypeReference() {}); + + String authToken = responseEntity.getHeaders().getFirst("authorization"); + return authToken; + } + + @CacheEvict(value = AUTH_TOKEN_CACHE, allEntries = true) + public void purgeAuthTokenCache() { + log.info("Evicting entry from AUTH_TOKEN_CACHE"); + } + +} diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCITransactionHelper.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCITransactionHelper.java index 0f02b57d..1081cbf3 100644 --- a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCITransactionHelper.java +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/helper/VCITransactionHelper.java @@ -14,6 +14,7 @@ @Component @ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "IdaVCIssuancePluginImpl") +@Deprecated public class VCITransactionHelper { @Autowired diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/HelperService.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/HelperService.java index e86bd951..c3bc36f1 100644 --- a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/HelperService.java +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/HelperService.java @@ -13,17 +13,20 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + import java.nio.charset.StandardCharsets; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.Base64; +import java.util.*; +import java.util.stream.Collectors; @Service @Slf4j -@ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "IdaVCIssuancePluginImpl") +@ConditionalOnProperty(value = "mosip.certify.integration.data-provider-plugin", havingValue = "IdaDataProviderPluginImpl") public class HelperService { public static final String UTC_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; @@ -42,7 +45,7 @@ protected String getRequestSignature(String request) { JWTSignatureRequestDto jwtSignatureRequestDto = new JWTSignatureRequestDto(); jwtSignatureRequestDto.setApplicationId(OIDC_PARTNER_APP_ID); jwtSignatureRequestDto.setReferenceId(""); - jwtSignatureRequestDto.setIncludePayload(false); + jwtSignatureRequestDto.setIncludePayload(true); jwtSignatureRequestDto.setIncludeCertificate(true); jwtSignatureRequestDto.setDataToSign(HelperService.b64Encode(request)); JWTSignatureResponseDto responseDto = signatureService.jwtSign(jwtSignatureRequestDto); @@ -60,4 +63,18 @@ protected static String b64Encode(String value) { return urlSafeEncoder.encodeToString(value.getBytes(StandardCharsets.UTF_8)); } + //Converts an array of two-letter language codes to their corresponding ISO 639-2/T language codes. + protected List convertLangCodesToISO3LanguageCodes(String[] langCodes) { + if(langCodes == null || langCodes.length == 0) + return List.of(); + return Arrays.stream(langCodes) + .map(langCode -> { + try { + return StringUtils.isEmpty(langCode) ? null : new Locale(langCode).getISO3Language(); + } catch (MissingResourceException ex) {} + return null; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } } diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java new file mode 100644 index 00000000..fbac2e24 --- /dev/null +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaDataProviderPluginImpl.java @@ -0,0 +1,247 @@ +package io.mosip.certify.mosipid.integration.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.certify.api.exception.DataProviderExchangeException; +import io.mosip.certify.api.spi.DataProviderPlugin; +import io.mosip.certify.mosipid.integration.dto.*; +import io.mosip.certify.mosipid.integration.helper.TransactionHelper; +import io.mosip.esignet.api.dto.*; +import io.mosip.esignet.api.exception.KycExchangeException; +import io.mosip.esignet.core.dto.OIDCTransaction; +import io.mosip.kernel.core.keymanager.spi.KeyStore; +import io.mosip.kernel.keymanagerservice.constant.KeymanagerConstant; +import io.mosip.kernel.keymanagerservice.entity.KeyAlias; +import io.mosip.kernel.keymanagerservice.helper.KeymanagerDBHelper; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONException; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.crypto.Cipher; +import java.security.Key; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.*; + +@Component +@Slf4j +@ConditionalOnProperty(value = "mosip.certify.integration.data-provider-plugin", havingValue = "IdaDataProviderPluginImpl") +public class IdaDataProviderPluginImpl implements DataProviderPlugin { + // TODO: Clean up code + // TODO: Write unit tests + + private static final String ACCESS_TOKEN_HASH = "accessTokenHash"; + public static final String SIGNATURE_HEADER_NAME = "signature"; + public static final String AUTHORIZATION_HEADER_NAME = "Authorization"; + public static final String OIDC_SERVICE_APP_ID = "CERTIFY_SERVICE"; + public static final String AES_CIPHER_FAILED = "aes_cipher_failed"; + public static final String NO_UNIQUE_ALIAS = "no_unique_alias"; + + @Value("${mosip.certify.authenticator.ida-version:1.0}") + private String idaVersion; + + @Value("${mosip.certify.authenticator.ida.kyc-exchange-url}") + private String kycExchangeUrl; + + @Value("${mosip.certify.ida.kyc-exchange-id:mosip.identity.kycexchange}") + private String kycExchangeId; + + @Value("${mosip.certify.cache.secure.individual-id}") + private boolean secureIndividualId; + + @Value("${mosip.certify.cache.store.individual-id}") + private boolean storeIndividualId; + + @Value("${mosip.certify.cache.security.algorithm-name}") + private String aesECBTransformation; + + @Value("${mosip.certify.cache.security.secretkey.reference-id}") + private String cacheSecretKeyRefId; + + @Value("#{'${mosip.certify.ida.kyc-exchange.accepted-claims}'.split(',')}") + private List kycExchangeAcceptedClaims; + + @Value("${mosip.certify.ida.kyc-exchange.accepted-locales:en}") + private String[] kycAcceptedLocales; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private RestTemplate restTemplate; + + @Autowired + HelperService helperService; + + @Autowired + private KeyStore keyStore; + + @Autowired + private KeymanagerDBHelper dbHelper; + + @Autowired + TransactionHelper transactionHelper; + + private Base64.Decoder urlSafeDecoder = Base64.getUrlDecoder(); + + @Override + public JSONObject fetchData(Map identityDetails) throws DataProviderExchangeException { + try { + KycExchangeResult kycExchangeResult = doKycExchange(identityDetails); + if(kycExchangeResult != null) { + log.info("Kyc Exchange Success."); + String encryptedKyc = kycExchangeResult.getEncryptedKyc(); + log.debug("Encrypted KYC: {}", encryptedKyc); + Map claims = decodeClaimsFromJwt(encryptedKyc); + log.debug("JWT Claims: {}", claims); + + return new JSONObject(claims); + } + } + catch (JSONException | JsonProcessingException e) { + log.error("Error occurred during json processing: " + e.getMessage()); + throw new DataProviderExchangeException("JSON_PARSING_FAILED", e.getMessage()); + } + catch (Exception e) { + log.error("ERROR_FETCHING_KYC_DATA. " + e.getMessage()); + throw new DataProviderExchangeException("ERROR_FETCHING_KYC_DATA", e.getMessage()); + } + throw new DataProviderExchangeException("ERROR_FETCHING_KYC_DATA", "No data found for kyc exchange"); + } + + private KycExchangeDto buildKycExchangeDto(OIDCTransaction transaction) throws Exception { + KycExchangeDto kycExchangeDto = new KycExchangeDto(); + + String individualId = getIndividualId(transaction.getIndividualId()); + kycExchangeDto.setIndividualId(individualId); + kycExchangeDto.setTransactionId(transaction.getAuthTransactionId()); + kycExchangeDto.setKycToken(transaction.getKycToken()); + kycExchangeDto.setAcceptedClaims(kycExchangeAcceptedClaims); + kycExchangeDto.setClaimsLocales(kycAcceptedLocales); + kycExchangeDto.setUserInfoResponseType(null); + + log.info("Built the KYC exchange DTO"); + + return kycExchangeDto; + } + + protected String getIndividualId(String encryptedIndividualId) throws Exception { + if (!storeIndividualId) + return null; + return secureIndividualId ? decryptIndividualId(encryptedIndividualId) : encryptedIndividualId; + } + + private String decryptIndividualId(String encryptedIndividualId) throws Exception { + try { + Cipher cipher = Cipher.getInstance(aesECBTransformation); + byte[] decodedBytes = b64Decode(encryptedIndividualId); + cipher.init(Cipher.DECRYPT_MODE, getSecretKeyFromHSM()); + return new String(cipher.doFinal(decodedBytes, 0, decodedBytes.length)); + } catch (Exception e) { + log.error("Error Cipher Operations of provided secret data.", e); + throw new Exception(AES_CIPHER_FAILED); + } + } + + private Key getSecretKeyFromHSM() throws Exception { + String keyAlias = getKeyAlias(OIDC_SERVICE_APP_ID, cacheSecretKeyRefId); + if (Objects.nonNull(keyAlias)) { + return keyStore.getSymmetricKey(keyAlias); + } + throw new Exception(NO_UNIQUE_ALIAS); + } + + private String getKeyAlias(String keyAppId, String keyRefId) throws Exception { + Map> keyAliasMap = dbHelper.getKeyAliases(keyAppId, keyRefId, + LocalDateTime.now(ZoneOffset.UTC)); + List currentKeyAliases = keyAliasMap.get(KeymanagerConstant.CURRENTKEYALIAS); + if (!currentKeyAliases.isEmpty() && currentKeyAliases.size() == 1) { + return currentKeyAliases.get(0).getAlias(); + } + log.error("CurrentKeyAlias is not unique. KeyAlias count: {}", currentKeyAliases.size()); + throw new Exception(NO_UNIQUE_ALIAS); + } + + private byte[] b64Decode(String value) { + return urlSafeDecoder.decode(value); + }; + + public KycExchangeResult doKycExchange(Map identityDetails) + throws Exception { + OIDCTransaction transaction = transactionHelper + .getOAuthTransaction(identityDetails.get(ACCESS_TOKEN_HASH).toString()); + KycExchangeDto kycExchangeDto = buildKycExchangeDto(transaction); + String relyingPartyId = transaction.getRelyingPartyId(); + String clientId = transaction.getClientId(); + return kycExchange(relyingPartyId, clientId, kycExchangeDto); + } + + private KycExchangeResult kycExchange(String relyingPartyId, String clientId, KycExchangeDto kycExchangeDto) + throws KycExchangeException { + log.info("Started to build kyc-exchange request with transactionId : {} && clientId : {}", + kycExchangeDto.getTransactionId(), clientId); + try { + IdaKycExchangeRequest idaKycExchangeRequest = new IdaKycExchangeRequest(); + idaKycExchangeRequest.setId(kycExchangeId); + idaKycExchangeRequest.setVersion(idaVersion); + idaKycExchangeRequest.setRequestTime(HelperService.getUTCDateTime()); + idaKycExchangeRequest.setTransactionID(kycExchangeDto.getTransactionId()); + idaKycExchangeRequest.setKycToken(kycExchangeDto.getKycToken()); + idaKycExchangeRequest.setConsentObtained(kycExchangeDto.getAcceptedClaims()); + idaKycExchangeRequest.setLocales(helperService.convertLangCodesToISO3LanguageCodes(kycExchangeDto.getClaimsLocales())); + idaKycExchangeRequest.setRespType(kycExchangeDto.getUserInfoResponseType()); // Setting the Response Type to null will give the final result as a JWT + idaKycExchangeRequest.setIndividualId(kycExchangeDto.getIndividualId()); + + log.info("Built the kyc exchange request"); + + //set signature header, body and invoke kyc exchange endpoint + String requestBody = objectMapper.writeValueAsString(idaKycExchangeRequest); + RequestEntity requestEntity = RequestEntity + .post(UriComponentsBuilder.fromUriString(kycExchangeUrl).pathSegment(relyingPartyId, + clientId).build().toUri()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .header(SIGNATURE_HEADER_NAME, helperService.getRequestSignature(requestBody)) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_NAME) + .body(requestBody); + ResponseEntity> responseEntity = restTemplate.exchange(requestEntity, + new ParameterizedTypeReference>() {}); + + if(responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) { + IdaResponseWrapper responseWrapper = responseEntity.getBody(); + if(responseWrapper.getResponse() != null && responseWrapper.getResponse().getEncryptedKyc() != null) { + return new KycExchangeResult(responseWrapper.getResponse().getEncryptedKyc()); + } + log.error("Errors in response received from IDA Kyc Exchange: {}", responseWrapper.getErrors()); + throw new KycExchangeException(CollectionUtils.isEmpty(responseWrapper.getErrors()) ? + io.mosip.esignet.api.util.ErrorConstants.DATA_EXCHANGE_FAILED : responseWrapper.getErrors().get(0).getErrorCode()); + } + + log.error("Error response received from IDA (Kyc-exchange) with status : {}", responseEntity.getStatusCode()); + } catch (KycExchangeException e) { throw e; } catch (Exception e) { + log.error("IDA Kyc-exchange failed with clientId : {}", clientId, e); + } + throw new KycExchangeException(); + } + + private Map decodeClaimsFromJwt(String jwtToken) throws JsonProcessingException, DataProviderExchangeException { + String[] parts = jwtToken.split("\\."); + if(parts.length < 3) { + throw new DataProviderExchangeException("Invalid KYC Exchange response."); + } + String payload = new String(urlSafeDecoder.decode(parts[1])); + Map claims = objectMapper.readValue(payload, Map.class); + + return claims; + } +} diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImpl.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImpl.java index 5f7120c5..0dadcb34 100644 --- a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImpl.java +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImpl.java @@ -48,6 +48,7 @@ @Component @Slf4j @ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "IdaVCIssuancePluginImpl") +@Deprecated public class IdaVCIssuancePluginImpl implements VCIssuancePlugin { private static final String CLIENT_ID = "client_id"; private static final String ACCESS_TOKEN_HASH = "accessTokenHash"; @@ -64,7 +65,7 @@ public class IdaVCIssuancePluginImpl implements VCIssuancePlugin { private RestTemplate restTemplate; @Autowired - HelperService helperService; + VCIHelperService helperService; @Autowired private KeyStore keyStore; diff --git a/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/VCIHelperService.java b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/VCIHelperService.java new file mode 100644 index 00000000..ae40ee29 --- /dev/null +++ b/mosip-identity-certify-plugin/src/main/java/io/mosip/certify/mosipid/integration/service/VCIHelperService.java @@ -0,0 +1,66 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.certify.mosipid.integration.service; + + +import io.mosip.kernel.signature.dto.JWTSignatureRequestDto; +import io.mosip.kernel.signature.dto.JWTSignatureResponseDto; +import io.mosip.kernel.signature.service.SignatureService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.nio.charset.StandardCharsets; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + + +@Service +@Slf4j +@ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "IdaVCIssuancePluginImpl") +@Deprecated +public class VCIHelperService { + + public static final String UTC_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + public static final String OIDC_PARTNER_APP_ID = "CERTIFY_PARTNER"; + private static Base64.Encoder urlSafeEncoder; + + static { + urlSafeEncoder = Base64.getUrlEncoder().withoutPadding(); + } + + + @Autowired + private SignatureService signatureService; + + protected String getRequestSignature(String request) { + JWTSignatureRequestDto jwtSignatureRequestDto = new JWTSignatureRequestDto(); + jwtSignatureRequestDto.setApplicationId(OIDC_PARTNER_APP_ID); + jwtSignatureRequestDto.setReferenceId(""); + jwtSignatureRequestDto.setIncludePayload(false); + jwtSignatureRequestDto.setIncludeCertificate(true); + jwtSignatureRequestDto.setDataToSign(HelperService.b64Encode(request)); + JWTSignatureResponseDto responseDto = signatureService.jwtSign(jwtSignatureRequestDto); + log.debug("Request signature ---> {}", responseDto.getJwtSignedData()); + return responseDto.getJwtSignedData(); + } + + protected static String getUTCDateTime() { + return ZonedDateTime + .now(ZoneOffset.UTC) + .format(DateTimeFormatter.ofPattern(UTC_DATETIME_PATTERN)); + } + + protected static String b64Encode(String value) { + return urlSafeEncoder.encodeToString(value.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaAuditPluginImplTest.java b/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaAuditPluginImplTest.java index 9f91eb76..0d498083 100644 --- a/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaAuditPluginImplTest.java +++ b/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaAuditPluginImplTest.java @@ -19,6 +19,10 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; +import java.time.LocalDateTime; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) @@ -144,4 +148,67 @@ public void getAuditDescription_shouldReturnValidJson() throws Exception { assert obj.getString("transactionId").equals("txn123"); assert obj.getString("idType").equals("UIN"); } + + // Add inside IdaAuditPluginImplTest + + @Test + public void auditRequest_gettersSetters_allArgsConstructor() { + LocalDateTime localDateTime = LocalDateTime.now(); + io.mosip.certify.mosipid.integration.dto.AuditRequest req1 = new io.mosip.certify.mosipid.integration.dto.AuditRequest( + "eventId", "eventName", "eventType", localDateTime, "hostName", "hostIp", + "appId", "appName", "sessionUserId", "sessionUserName", "id", "idType", + "createdBy", "moduleName", "moduleId", "desc" + ); + assertEquals("eventId", req1.getEventId()); + assertEquals("eventName", req1.getEventName()); + assertEquals("eventType", req1.getEventType()); + assertEquals(localDateTime, req1.getActionTimeStamp()); + assertEquals("hostName", req1.getHostName()); + assertEquals("hostIp", req1.getHostIp()); + assertEquals("appId", req1.getApplicationId()); + assertEquals("appName", req1.getApplicationName()); + assertEquals("sessionUserId", req1.getSessionUserId()); + assertEquals("sessionUserName", req1.getSessionUserName()); + assertEquals("idType", req1.getIdType()); + assertEquals("createdBy", req1.getCreatedBy()); + assertEquals("moduleName", req1.getModuleName()); + assertEquals("moduleId", req1.getModuleId()); + assertEquals("desc", req1.getDescription()); + assertEquals("id", req1.getId()); + + io.mosip.certify.mosipid.integration.dto.AuditRequest req2 = new io.mosip.certify.mosipid.integration.dto.AuditRequest(); + req2.setEventId("eventId"); + req2.setEventName("eventName"); + req2.setEventType("eventType"); + req2.setActionTimeStamp(localDateTime); + req2.setHostName("hostName"); + req2.setHostIp("hostIp"); + req2.setApplicationId("appId"); + req2.setApplicationName("appName"); + req2.setSessionUserId("sessionUserId"); + req2.setSessionUserName("sessionUserName"); + req2.setIdType("idType"); + req2.setCreatedBy("createdBy"); + req2.setModuleName("moduleName"); + req2.setModuleId("moduleId"); + req2.setDescription("desc"); + req2.setId("id"); + + assertEquals(req1, req2); + assertEquals(req1.hashCode(), req2.hashCode()); + assertTrue(req1.toString().contains("eventId")); + } + + @Test + public void auditResponse_gettersSetters_allArgsConstructor() { + AuditResponse resp1 = new AuditResponse(); + resp1.setStatus(true); + + AuditResponse resp2 = new AuditResponse(); + resp2.setStatus(true); + + assertEquals(resp1, resp2); + assertEquals(resp1.hashCode(), resp2.hashCode()); + assertEquals(resp1.toString(), resp2.toString()); + } } diff --git a/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImplTest.java b/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImplTest.java index d1d558a6..b727645a 100644 --- a/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImplTest.java +++ b/mosip-identity-certify-plugin/src/test/java/io/mosip/certify/mosipid/integration/service/IdaVCIssuancePluginImplTest.java @@ -13,9 +13,7 @@ import io.mosip.certify.api.exception.VCIExchangeException; import io.mosip.certify.api.util.ErrorConstants; import io.mosip.certify.core.exception.CertifyException; -import io.mosip.certify.mosipid.integration.dto.IdaResponseWrapper; -import io.mosip.certify.mosipid.integration.dto.IdaVcExchangeRequest; -import io.mosip.certify.mosipid.integration.dto.IdaVcExchangeResponse; +import io.mosip.certify.mosipid.integration.dto.*; import io.mosip.certify.mosipid.integration.helper.VCITransactionHelper; import io.mosip.esignet.core.dto.OIDCTransaction; import io.mosip.kernel.core.keymanager.spi.KeyStore; @@ -44,6 +42,8 @@ import java.util.*; import static io.mosip.kernel.keymanagerservice.constant.KeymanagerConstant.CURRENTKEYALIAS; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; @RunWith(MockitoJUnitRunner.class) public class IdaVCIssuancePluginImplTest { @@ -58,7 +58,7 @@ public class IdaVCIssuancePluginImplTest { RestTemplate restTemplate; @Mock - HelperService helperService; + VCIHelperService helperService; @Mock KeymanagerDBHelper keymanagerDBHelper; @@ -386,4 +386,157 @@ public void getIndividualId_whenSecureIndividualIdFalse_shouldReturnOriginalValu String result = idaVCIssuancePlugin.getIndividualId(expected); Assert.assertEquals(expected, result); } + + @Test + public void testIdaVcExchangeRequest() { + IdaVcExchangeRequest req1 = new IdaVcExchangeRequest(); + req1.setVcAuthToken("token"); + req1.setCredSubjectId("subjectId"); + req1.setVcFormat("format"); + req1.setLocales(List.of("en", "fr")); + req1.setMetadata(Map.of("key", "value")); + req1.setId("id"); + req1.setVersion("v1"); + req1.setIndividualId("indivId"); + req1.setTransactionID("txnId"); + req1.setRequestTime("now"); + CredentialDefinitionDTO credDef = new CredentialDefinitionDTO(); + req1.setCredentialsDefinition(credDef); + + assertEquals("token", req1.getVcAuthToken()); + assertEquals("subjectId", req1.getCredSubjectId()); + assertEquals("format", req1.getVcFormat()); + assertEquals(List.of("en", "fr"), req1.getLocales()); + assertEquals(Map.of("key", "value"), req1.getMetadata()); + assertEquals("id", req1.getId()); + assertEquals("v1", req1.getVersion()); + assertEquals("indivId", req1.getIndividualId()); + assertEquals("txnId", req1.getTransactionID()); + assertEquals("now", req1.getRequestTime()); + assertEquals(credDef, req1.getCredentialsDefinition()); + + IdaVcExchangeRequest req2 = new IdaVcExchangeRequest(); + req2.setVcAuthToken("token"); + req2.setCredSubjectId("subjectId"); + req2.setVcFormat("format"); + req2.setLocales(List.of("en", "fr")); + req2.setMetadata(Map.of("key", "value")); + req2.setId("id"); + req2.setVersion("v1"); + req2.setIndividualId("indivId"); + req2.setTransactionID("txnId"); + req2.setRequestTime("now"); + req2.setCredentialsDefinition(credDef); + + assertEquals(req1, req2); + assertEquals(req1.hashCode(), req2.hashCode()); + assertTrue(req1.toString().contains("token")); + } + + @Test + public void testIdaVcExchangeResponse() { + IdaVcExchangeResponse resp1 = new IdaVcExchangeResponse<>(); + resp1.setVerifiableCredentials("vc"); + assertEquals("vc", resp1.getVerifiableCredentials()); + + IdaVcExchangeResponse resp2 = new IdaVcExchangeResponse<>(); + resp2.setVerifiableCredentials("vc"); + + assertEquals(resp1, resp2); + assertEquals(resp1.hashCode(), resp2.hashCode()); + assertTrue(resp1.toString().contains("vc")); + } + + @Test + public void testIdaError() { + IdaError err1 = new IdaError(); + err1.setActionMessage("action"); + err1.setErrorCode("code"); + err1.setErrorMessage("msg"); + + assertEquals("action", err1.getActionMessage()); + assertEquals("code", err1.getErrorCode()); + assertEquals("msg", err1.getErrorMessage()); + + IdaError err2 = new IdaError(); + err2.setActionMessage("action"); + err2.setErrorCode("code"); + err2.setErrorMessage("msg"); + + assertEquals(err1, err2); + assertEquals(err1.hashCode(), err2.hashCode()); + assertTrue(err1.toString().contains("action")); + } + + @Test + public void testCredentialDefinitionDTO() { + CredentialDefinitionDTO dto1 = new CredentialDefinitionDTO(); + dto1.setCredentialSubject(Map.of("key", "value")); + dto1.setType(List.of("type1", "type2")); + dto1.setContext(List.of("context1", "context2")); + + assertEquals(Map.of("key", "value"), dto1.getCredentialSubject()); + assertEquals(List.of("type1", "type2"), dto1.getType()); + assertEquals(List.of("context1", "context2"), dto1.getContext()); + + CredentialDefinitionDTO dto2 = new CredentialDefinitionDTO(); + dto2.setCredentialSubject(Map.of("key", "value")); + dto2.setType(List.of("type1", "type2")); + dto2.setContext(List.of("context1", "context2")); + + assertEquals(dto1, dto2); + assertEquals(dto1.hashCode(), dto2.hashCode()); + assertTrue(dto1.toString().contains("key")); + } + + @Test + public void testClientIdSecretKeyRequest() { + // All-args constructor + ClientIdSecretKeyRequest req1 = new ClientIdSecretKeyRequest("client", "secret", "app"); + assertEquals("client", req1.getClientId()); + assertEquals("secret", req1.getSecretKey()); + assertEquals("app", req1.getAppId()); + + // No-args constructor and setters + ClientIdSecretKeyRequest req2 = new ClientIdSecretKeyRequest(); + req2.setClientId("client"); + req2.setSecretKey("secret"); + req2.setAppId("app"); + + assertEquals(req1, req2); + assertEquals(req1.hashCode(), req2.hashCode()); + assertTrue(req1.toString().contains("client")); + } + + @Test + public void testIdaResponseWrapper() { + IdaResponseWrapper wrapper1 = new IdaResponseWrapper<>(); + wrapper1.setId("id1"); + wrapper1.setVersion("v1"); + wrapper1.setTransactionID("txn1"); + wrapper1.setResponseTime("now"); + wrapper1.setResponse("response"); + IdaError error = new IdaError(); + error.setErrorCode("E1"); + wrapper1.setErrors(List.of(error)); + + assertEquals("id1", wrapper1.getId()); + assertEquals("v1", wrapper1.getVersion()); + assertEquals("txn1", wrapper1.getTransactionID()); + assertEquals("now", wrapper1.getResponseTime()); + assertEquals("response", wrapper1.getResponse()); + assertEquals(List.of(error), wrapper1.getErrors()); + + IdaResponseWrapper wrapper2 = new IdaResponseWrapper<>(); + wrapper2.setId("id1"); + wrapper2.setVersion("v1"); + wrapper2.setTransactionID("txn1"); + wrapper2.setResponseTime("now"); + wrapper2.setResponse("response"); + wrapper2.setErrors(List.of(error)); + + assertEquals(wrapper1, wrapper2); + assertEquals(wrapper1.hashCode(), wrapper2.hashCode()); + assertTrue(wrapper1.toString().contains("id1")); + } } diff --git a/postgres-dataprovider-plugin/README.md b/postgres-dataprovider-plugin/README.md index 8f7b76cf..c9aed7b5 100644 --- a/postgres-dataprovider-plugin/README.md +++ b/postgres-dataprovider-plugin/README.md @@ -104,11 +104,11 @@ sequenceDiagram ``` - When the authentication is done using this particular identifier then the record from certify tables can be fetched by the postgres plugin and returned as a JSON Object. -2. For referring the table creation and template insertion, see the sql scripts under db_scripts/mosip_certify/ddl folder of inji_certify: [db_scripts](https://github.com/mosip/inji-certify/tree/master/db_scripts/mosip_certify/ddl) +2. For referring the table creation and template insertion, see the sql scripts under db_scripts/mosip_certify/ddl folder of inji_certify: [db_scripts](https://github.com/inji/inji-certify/tree/master/db_scripts/mosip_certify/ddl) 3. inji-config changes: - - Refer to the properties file in [inji-config](https://github.com/mosip/inji-config) that corresponds to the postgres plugin implementation. - [Certify Postgres Land Registry](https://github.com/mosip/inji-config/blob/develop/certify-postgres-landregistry.properties) + - Refer to the properties file in [inji-config](https://github.com/inji/inji-config) that corresponds to the postgres plugin implementation. + [Certify Postgres Land Registry](https://github.com/inji/inji-config/blob/develop/certify-postgres-landregistry.properties) - The value for the property `mosip.certify.integration.data-provider-plugin` must be set to `PostgresDataProviderPlugin` - Refer to the below property for setting the query value against the scope for the credential that is to be issued: ``` diff --git a/postgres-dataprovider-plugin/pom.xml b/postgres-dataprovider-plugin/pom.xml index 71423c2c..5d8dea2c 100644 --- a/postgres-dataprovider-plugin/pom.xml +++ b/postgres-dataprovider-plugin/pom.xml @@ -2,14 +2,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.mosip.certify + io.inji.certify postgres-dataprovider-plugin - 0.4.0-SNAPSHOT + 0.6.0-SNAPSHOT jar postgres-dataprovider-plugin Data provider plugin implementation through postgres db that is used to showcase the integration with certify - https://github.com/mosip/digital-credential-plugins + https://github.com/inji/digital-credential-plugins @@ -18,17 +18,17 @@ - scm:git:git://github.com/mosip/digital-credential-plugins.git - scm:git:ssh://github.com:mosip/digital-credential-plugins.git - https://github.com/mosip/digital-credential-plugins + scm:git:git://github.com/inji/digital-credential-plugins.git + scm:git:ssh://github.com:inji/digital-credential-plugins.git + https://github.com/inji/digital-credential-plugins HEAD MOSIP mosip.emailnotifier@gmail.com - io.mosip - https://www.mosip.io + io.inji + https://inji.io @@ -42,7 +42,7 @@ 3.2.5 1.5 2.2.1 - 6.1.0 + 0.7.0 3.0.1 0.8.11 3.6.3 @@ -56,9 +56,9 @@ provided - io.mosip.certify + io.inji.certify certify-core - 0.11.0-SNAPSHOT + 0.14.0-SNAPSHOT provided @@ -92,9 +92,9 @@ - ossrh - CentralRepository - https://oss.sonatype.org/content/repositories/snapshots + ossrh-central + MavenCentralRepository + https://central.sonatype.com/repository/maven-snapshots default true @@ -114,14 +114,13 @@ ossrh - https://oss.sonatype.org/content/repositories/snapshots + https://central.sonatype.com/repository/maven-snapshots/ ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://central.sonatype.com/api/v1/publisher - @@ -176,26 +175,15 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.14 + org.sonatype.central + central-publishing-maven-plugin + ${central.publishing.maven.plugin.version} true - - - default-deploy - deploy - - deploy - - - - ossrh - https://oss.sonatype.org/ - false + ossrh + false - org.apache.maven.plugins maven-source-plugin diff --git a/postgres-dataprovider-plugin/src/test/java/io/mosip/certify/postgresdataprovider/integration/service/PostgresDataProviderPluginTest.java b/postgres-dataprovider-plugin/src/test/java/io/mosip/certify/postgresdataprovider/integration/service/PostgresDataProviderPluginTest.java index 5041c394..bf1a40e9 100644 --- a/postgres-dataprovider-plugin/src/test/java/io/mosip/certify/postgresdataprovider/integration/service/PostgresDataProviderPluginTest.java +++ b/postgres-dataprovider-plugin/src/test/java/io/mosip/certify/postgresdataprovider/integration/service/PostgresDataProviderPluginTest.java @@ -12,6 +12,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.exceptions.base.MockitoException; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; @@ -84,7 +85,7 @@ public void fetchJsonDataWithMissingSub_thenFail() throws DataProviderExchangeEx @Test(expected = DataProviderExchangeException.class) public void fetchJsonDataWithNullQueryResult_thenFail() throws DataProviderExchangeException { Mockito.when(dataProviderRepository.fetchQueryResult("1234567", "test_query")) - .thenReturn(null); + .thenThrow(new MockitoException("Query execution failed")); postgresDataProviderPlugin.fetchData(Map.of("sub", "1234567", "client_id", "CLIENT_ID", "scope", "test_vc_ldp")); } diff --git a/sunbird-rc-certify-integration-impl/pom.xml b/sunbird-rc-certify-integration-impl/pom.xml index 0e28380e..53a92da4 100644 --- a/sunbird-rc-certify-integration-impl/pom.xml +++ b/sunbird-rc-certify-integration-impl/pom.xml @@ -6,14 +6,14 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.mosip.certify.sunbirdrc + io.inji.certify.sunbirdrc sunbird-rc-certify-integration-impl - 0.4.0-SNAPSHOT + 0.6.0-SNAPSHOT jar sunbird-rc-certify-integration-impl Sunbird-RC plugin implementation that is used for the integration with certify - https://github.com/mosip/digital-credential-plugins + https://github.com/inji/digital-credential-plugins @@ -22,17 +22,17 @@ - scm:git:git://github.com/mosip/digital-credential-plugins.git - scm:git:ssh://github.com:mosip/digital-credential-plugins.git - https://github.com/mosip/digital-credential-plugins + scm:git:git://github.com/inji/digital-credential-plugins.git + scm:git:ssh://github.com:inji/digital-credential-plugins.git + https://github.com/inji/digital-credential-plugins HEAD Mosip mosip.emailnotifier@gmail.com - io.mosip - https://www.mosip.io + io.inji + https://inji.io @@ -45,16 +45,16 @@ 3.2.5 1.5 2.2.1 - 6.1.0 + 0.7.0 3.0.1 0.8.11 3.6.3 - io.mosip.certify + io.inji.certify certify-integration-api - 0.11.0-SNAPSHOT + 0.14.0-SNAPSHOT provided @@ -77,11 +77,16 @@ 3.4.3 test + + + + + + - org.springframework.boot - spring-boot-starter-test - 3.2.3 - test + org.springframework + spring-test + 6.1.4 @@ -99,12 +104,18 @@ + + junit + junit + 4.13.2 + test + - ossrh - CentralRepository - https://oss.sonatype.org/content/repositories/snapshots + ossrh-central + MavenCentralRepository + https://central.sonatype.com/repository/maven-snapshots default true @@ -132,11 +143,11 @@ ossrh - https://oss.sonatype.org/content/repositories/snapshots + https://central.sonatype.com/repository/maven-snapshots/ ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://central.sonatype.com/api/v1/publisher @@ -193,26 +204,15 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.14 + org.sonatype.central + central-publishing-maven-plugin + ${central.publishing.maven.plugin.version} true - - - default-deploy - deploy - - deploy - - - - ossrh - https://oss.sonatype.org/ - false + ossrh + false - org.apache.maven.plugins maven-source-plugin diff --git a/sunbird-rc-certify-integration-impl/src/test/java/io/mosip/certify/sunbirdrc/integration/service/SunbirdRCVCIssuancePluginTest.java b/sunbird-rc-certify-integration-impl/src/test/java/io/mosip/certify/sunbirdrc/integration/service/SunbirdRCVCIssuancePluginTest.java index 50b02d63..e5a5fa24 100644 --- a/sunbird-rc-certify-integration-impl/src/test/java/io/mosip/certify/sunbirdrc/integration/service/SunbirdRCVCIssuancePluginTest.java +++ b/sunbird-rc-certify-integration-impl/src/test/java/io/mosip/certify/sunbirdrc/integration/service/SunbirdRCVCIssuancePluginTest.java @@ -18,7 +18,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.boot.test.context.SpringBootTest; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.env.Environment; import org.springframework.http.HttpStatus; @@ -34,7 +34,7 @@ import java.util.Map; @RunWith(MockitoJUnitRunner.class) -@SpringBootTest +//@SpringBootTest public class SunbirdRCVCIssuancePluginTest { @Mock diff --git a/sunbird-rc-esignet-integration-impl/pom.xml b/sunbird-rc-esignet-integration-impl/pom.xml index 80d81722..5a44c8e6 100644 --- a/sunbird-rc-esignet-integration-impl/pom.xml +++ b/sunbird-rc-esignet-integration-impl/pom.xml @@ -4,12 +4,12 @@ 4.0.0 io.mosip.esignet.sunbirdrc sunbird-rc-esignet-integration-impl - 0.4.0-SNAPSHOT + 0.5.0-SNAPSHOT jar sunbird-rc-esignet-integration-impl Sunbird-RC plugin implementation that is used for the integration with eSignet - https://github.com/mosip/digital-credential-plugins + https://github.com/inji/digital-credential-plugins @@ -18,9 +18,9 @@ - scm:git:git://github.com/mosip/digital-credential-plugins.git - scm:git:ssh://github.com:mosip/digital-credential-plugins.git - https://github.com/mosip/digital-credential-plugins + scm:git:git://github.com/inji/digital-credential-plugins.git + scm:git:ssh://github.com:inji/digital-credential-plugins.git + https://github.com/inji/digital-credential-plugins HEAD @@ -28,7 +28,7 @@ Mosip mosip.emailnotifier@gmail.com io.mosip - https://github.com/mosip/digital-credential-plugins + https://www.mosip.io @@ -43,7 +43,7 @@ 2.22.0 1.5 2.2.1 - 1.6.7 + 0.7.0 3.0.1 0.8.5 3.3.1 @@ -120,9 +120,9 @@ - ossrh - CentralRepository - https://oss.sonatype.org/content/repositories/snapshots + ossrh-central + MavenCentralRepository + https://central.sonatype.com/repository/maven-snapshots default true @@ -149,14 +149,14 @@ - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + ossrh + https://central.sonatype.com/repository/maven-snapshots/ + + + ossrh + https://central.sonatype.com/api/v1/publisher + + @@ -211,26 +211,15 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 + org.sonatype.central + central-publishing-maven-plugin + ${central.publishing.maven.plugin.version} true - - - default-deploy - deploy - - deploy - - - - ossrh - https://oss.sonatype.org/ - false + ossrh + false - org.apache.maven.plugins maven-source-plugin