diff --git a/revocation-service/src/main/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationService.java b/revocation-service/src/main/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationService.java index f0ebd35c..ab273c17 100644 --- a/revocation-service/src/main/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationService.java +++ b/revocation-service/src/main/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationService.java @@ -25,6 +25,8 @@ import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.eclipse.tractusx.managedidentitywallets.commons.constant.CredentialStatus; +import org.eclipse.tractusx.managedidentitywallets.commons.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.commons.exception.BadDataException; import org.eclipse.tractusx.managedidentitywallets.revocation.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.revocation.constant.RevocationApiEndpoints; @@ -89,10 +91,19 @@ public class RevocationService { private final MIWSettings miwSettings; + /** + * Verifies the status of a credential based on the provided CredentialStatusDto object. + * + * @param statusDto The CredentialStatusDto object containing the necessary information for status verification. + * @return A Map object with the key "status" and the value "revoked" or "active" indicating the status of the credential. + * @throws BadDataException If the status list VC is not found for the issuer. + */ @Transactional public Map verifyStatus(CredentialStatusDto statusDto) { + validateCredentialStatus(statusDto); + String url = statusDto.statusListCredential(); String[] values = CommonUtils.extractValuesFromURL(url); @@ -106,13 +117,12 @@ public Map verifyStatus(CredentialStatusDto statusDto) { //validate status list VC validateStatusListVC(statusListCredential); - String encodedList = statusListCredential.getCredentialSubject().get(0).get(ENCODED_LIST).toString(); BitSet bitSet = BitSetManager.decompress(BitSetManager.decodeFromString(encodedList)); int index = Integer.parseInt(statusDto.statusListIndex()); boolean status = bitSet.get(index); - return Map.of("status", status ? "revoked" : "active"); + return Map.of(StringPool.STATUS, status ? CredentialStatus.REVOKED.getName() : CredentialStatus.ACTIVE.getName()); } diff --git a/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationServiceTest.java b/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationServiceTest.java index 3d98c148..728ec0d2 100644 --- a/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationServiceTest.java +++ b/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/RevocationServiceTest.java @@ -22,6 +22,9 @@ package org.eclipse.tractusx.managedidentitywallets.revocation.services; import com.fasterxml.jackson.core.JsonProcessingException; +import lombok.SneakyThrows; +import org.eclipse.tractusx.managedidentitywallets.commons.constant.CredentialStatus; +import org.eclipse.tractusx.managedidentitywallets.commons.constant.StringPool; import org.eclipse.tractusx.managedidentitywallets.revocation.TestUtil; import org.eclipse.tractusx.managedidentitywallets.revocation.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.revocation.dto.CredentialStatusDto; @@ -33,8 +36,11 @@ import org.eclipse.tractusx.managedidentitywallets.revocation.repository.StatusListCredentialRepository; import org.eclipse.tractusx.managedidentitywallets.revocation.repository.StatusListIndexRepository; import org.eclipse.tractusx.managedidentitywallets.revocation.utils.BitSetManager; +import org.eclipse.tractusx.ssi.lib.did.resolver.DidResolver; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialSubject; +import org.eclipse.tractusx.ssi.lib.proof.LinkedDataProofValidation; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -49,6 +55,7 @@ import java.util.Base64; import java.util.BitSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -107,6 +114,95 @@ public void beforeEach() { Mockito.reset(statusListCredentialRepository, statusListIndexRepository, httpClientService); } + + @Nested + class VerifyStatusTest { + @SneakyThrows + @Test + void shouldVerifyStatusActive() { + final var issuer = DID; + var encodedList = mockEmptyEncodedList(); + var credentialBuilder = mockStatusListVC(issuer, "1", encodedList); + var statusListCredential = mockStatusListCredential(issuer, credentialBuilder); + // 1. create status list with the credential + var statusListIndex = mockStatusListIndex(issuer, statusListCredential, "0"); + when(statusListIndex.getStatusListCredential()).thenReturn(statusListCredential); + when(statusListCredentialRepository.findById(any(String.class))) + .thenReturn(Optional.of(statusListCredential)); + CredentialStatusDto credentialStatusDto = Mockito.mock(CredentialStatusDto.class); + when(credentialStatusDto.id()) + .thenReturn( + "http://this-is-my-domain/api/v1/revocations/credentials/" + + TestUtil.extractBpnFromDid(issuer) + + "/revocation/1#0"); + when(credentialStatusDto.statusPurpose()).thenReturn("revocation"); + when(credentialStatusDto.statusListIndex()).thenReturn("0"); + when(credentialStatusDto.statusListCredential()) + .thenReturn( + "http://this-is-my-domain/api/v1/revocations/credentials/" + + TestUtil.extractBpnFromDid(issuer) + + "/revocation/1"); + when(credentialStatusDto.type()).thenReturn("BitstringStatusListEntry"); + + + try (MockedStatic utils = Mockito.mockStatic(LinkedDataProofValidation.class)) { + LinkedDataProofValidation mock = Mockito.mock(LinkedDataProofValidation.class); + utils.when(() -> { + LinkedDataProofValidation.newInstance(Mockito.any(DidResolver.class)); + }).thenReturn(mock); + Mockito.when(mock.verify(Mockito.any(VerifiableCredential.class))).thenReturn(true); + Map status = revocationService.verifyStatus(credentialStatusDto); + Assertions.assertTrue(status.get(StringPool.STATUS).equals(CredentialStatus.ACTIVE.getName())); + } + } + + @SneakyThrows + @Test + void shouldVerifyStatusRevoke() { + + String indexTORevoke = "0"; + final var issuer = DID; + + //set bit at index + String encodedList = mockEmptyEncodedList(); + encodedList = BitSetManager.revokeCredential(encodedList, Integer.parseInt(indexTORevoke)); + + + var credentialBuilder = mockStatusListVC(issuer, "1", encodedList); + var statusListCredential = mockStatusListCredential(issuer, credentialBuilder); + // 1. create status list with the credential + var statusListIndex = mockStatusListIndex(issuer, statusListCredential, "0"); + when(statusListIndex.getStatusListCredential()).thenReturn(statusListCredential); + when(statusListCredentialRepository.findById(any(String.class))) + .thenReturn(Optional.of(statusListCredential)); + CredentialStatusDto credentialStatusDto = Mockito.mock(CredentialStatusDto.class); + when(credentialStatusDto.id()) + .thenReturn( + "http://this-is-my-domain/api/v1/revocations/credentials/" + + TestUtil.extractBpnFromDid(issuer) + + "/revocation/1#0"); + when(credentialStatusDto.statusPurpose()).thenReturn("revocation"); + when(credentialStatusDto.statusListIndex()).thenReturn(indexTORevoke); + when(credentialStatusDto.statusListCredential()) + .thenReturn( + "http://this-is-my-domain/api/v1/revocations/credentials/" + + TestUtil.extractBpnFromDid(issuer) + + "/revocation/1"); + when(credentialStatusDto.type()).thenReturn("BitstringStatusListEntry"); + try (MockedStatic utils = Mockito.mockStatic(LinkedDataProofValidation.class)) { + LinkedDataProofValidation mock = Mockito.mock(LinkedDataProofValidation.class); + utils.when(() -> { + LinkedDataProofValidation.newInstance(Mockito.any(DidResolver.class)); + }).thenReturn(mock); + Mockito.when(mock.verify(Mockito.any(VerifiableCredential.class))).thenReturn(true); + Map status = revocationService.verifyStatus(credentialStatusDto); + + Assertions.assertTrue(status.get(StringPool.STATUS).equals(CredentialStatus.REVOKED.getName())); + } + } + } + + @Nested class RevokeTest { diff --git a/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/StatusVerificationTest.java b/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/StatusVerificationTest.java new file mode 100644 index 00000000..80a83706 --- /dev/null +++ b/revocation-service/src/test/java/org/eclipse/tractusx/managedidentitywallets/revocation/services/StatusVerificationTest.java @@ -0,0 +1,33 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + +package org.eclipse.tractusx.managedidentitywallets.revocation.services; + +import org.junit.jupiter.api.Test; + +public class StatusVerificationTest { + + + @Test + void testVerification() { + + } +} diff --git a/wallet-commons/src/main/java/org/eclipse/tractusx/managedidentitywallets/commons/constant/StringPool.java b/wallet-commons/src/main/java/org/eclipse/tractusx/managedidentitywallets/commons/constant/StringPool.java index 5ee3fd5e..531b59a7 100644 --- a/wallet-commons/src/main/java/org/eclipse/tractusx/managedidentitywallets/commons/constant/StringPool.java +++ b/wallet-commons/src/main/java/org/eclipse/tractusx/managedidentitywallets/commons/constant/StringPool.java @@ -101,4 +101,6 @@ public class StringPool { public static final String CREDENTIAL_STATUS = "credentialStatus"; + public static final String STATUS = "status"; + }