diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java index 5b7fc0d09..edaea9ba7 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/MIWSettings.java @@ -22,10 +22,15 @@ package org.eclipse.tractusx.managedidentitywallets.config; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; /** * The type Miw settings. */ @ConfigurationProperties(prefix = "miw") -public record MIWSettings(String host, String encryptionKey, String authorityWalletBpn, String authorityWalletName) { +public record MIWSettings(String host, String encryptionKey, String authorityWalletBpn, String authorityWalletName, + List vcContexts, @DateTimeFormat(pattern = "dd-MM-yyyy") Date vcExpiryDate) { } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java index 6c5d1f10c..049514f3c 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java @@ -73,9 +73,12 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers(new AntPathRequestMatcher(RestURI.WALLETS, POST.name())).hasRole(ApplicationConstant.ROLE_ADD_WALLETS) //Create wallet .requestMatchers(new AntPathRequestMatcher(RestURI.WALLETS, GET.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLETS) //Get all wallet .requestMatchers(new AntPathRequestMatcher(RestURI.API_WALLETS_IDENTIFIER, GET.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //get wallet by BPN - .requestMatchers(new AntPathRequestMatcher(RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, POST.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //Store credential + .requestMatchers(new AntPathRequestMatcher(RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLETS, ApplicationConstant.ROLE_UPDATE_WALLET) //Store credential .requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS, GET.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //get credentials - .requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLETS, ApplicationConstant.ROLE_UPDATE_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //issue Membership Credential + .requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLETS, ApplicationConstant.ROLE_UPDATE_WALLET) //issue Membership Credential + .requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS_ISSUER_DISMANTLER, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLETS, ApplicationConstant.ROLE_UPDATE_WALLET) //issue dismantler Credential + .requestMatchers(new AntPathRequestMatcher(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLETS, ApplicationConstant.ROLE_UPDATE_WALLET) //issue dismantler Credential + .requestMatchers(new AntPathRequestMatcher("/error")).permitAll() .and().oauth2ResourceServer() .jwt() diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java new file mode 100644 index 000000000..173334a7d --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/MIWVerifiableCredentialType.java @@ -0,0 +1,40 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.constant; + +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialType; + +/** + * The type Miw verifiable credential type. + */ +public class MIWVerifiableCredentialType extends VerifiableCredentialType { + + /** + * The constant DISMANTLER_CREDENTIAL_CX. + */ + public static final String DISMANTLER_CREDENTIAL_CX = "DismantlerCredentialCX"; + + /** + * The constant USE_CASE_FRAMEWORK_CONDITION_CX. + */ + public static final String USE_CASE_FRAMEWORK_CONDITION_CX = "UseCaseFrameworkConditionCX"; +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java index 2bf30fc1e..0343ad61a 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/constant/RestURI.java @@ -57,4 +57,14 @@ private RestURI() { */ public static final String CREDENTIALS_ISSUER_MEMBERSHIP = "/api/credentials/issuer/membership"; + /** + * The constant CREDENTIALS_ISSUER_DISMANTLER. + */ + public static final String CREDENTIALS_ISSUER_DISMANTLER = "/api/credentials/issuer/dismantler"; + + /** + * The constant API_CREDENTIALS_ISSUER_FRAMEWORK. + */ + public static final String API_CREDENTIALS_ISSUER_FRAMEWORK = "/api/credentials/issuer/framework"; + } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java index 0504bf925..04bded85c 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/CredentialController.java @@ -27,6 +27,8 @@ import lombok.RequiredArgsConstructor; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.service.CredentialService; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -73,4 +75,28 @@ public ResponseEntity> getCredentials(@RequestParam(required = public ResponseEntity issueMembershipCredential(@Valid @RequestBody IssueMembershipCredentialRequest issueMembershipCredentialRequest) { return ResponseEntity.status(HttpStatus.CREATED).body(service.issueMembershipCredential(issueMembershipCredentialRequest)); } + + /** + * Issue dismantler credential response entity. + * + * @param request the request + * @return the response entity + */ + @Operation(summary = "Issue a Dismantler Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + @PostMapping(path = RestURI.CREDENTIALS_ISSUER_DISMANTLER, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity issueDismantlerCredential(@Valid @RequestBody IssueDismantlerCredentialRequest request) { + return ResponseEntity.status(HttpStatus.CREATED).body(service.issueDismantlerCredential(request)); + } + + /** + * Issue framework credential response entity. + * + * @param request the request + * @return the response entity + */ + @Operation(summary = "Issue a Use Case Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + @PostMapping(path = RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity issueFrameworkCredential(@Valid @RequestBody IssueFrameworkCredentialRequest request) { + return ResponseEntity.status(HttpStatus.CREATED).body(service.issueFrameworkCredential(request)); + } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java index 515a7a0d2..1076522c8 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java @@ -22,6 +22,8 @@ package org.eclipse.tractusx.managedidentitywallets.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -68,6 +70,41 @@ public ResponseEntity createWallet(@Valid @RequestBody CreateWalletReque */ @Operation(summary = "Store Verifiable Credential", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of wallet to extract credentials from must equal BPN of caller) \n\n Store a verifiable credential in the wallet of the given identifier") @PostMapping(path = RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + + @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "id": "http://example.edu/credentials/3732", + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "type": [ + "University-Degree-Credential, VerifiableCredential" + ], + "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", + "issuanceDate": "2019-06-16T18:56:59Z", + "expirationDate": "2019-06-17T18:56:59Z", + "credentialSubject": { + "college": "Test-University" + }, + "credentialStatus": { + "id": "http://example.edu/api/credentials/status/test#3", + "type": "StatusList2021Entry", + "statusPurpose": "revocation", + "statusListIndex": "3", + "statusListCredential": "http://example.edu/api/credentials/status/test" + }, + "proof": { + "type": "Ed25519Signature2018", + "created": "2021-11-17T22:20:27Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:example:76e12ec712ebc6f1c221ebfeb1f#key-1", + "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..JNerzfrK46Mq4XxYZEnY9xOK80xsEaWCLAHuZsFie1-NTJD17wWWENn_DAlA_OwxGF5dhxUJ05P6Dm8lcmF5Cg" + } + } + """)) + }) public ResponseEntity> storeCredential(@RequestBody Map data, @PathVariable(name = "identifier") String identifier) { return ResponseEntity.status(HttpStatus.CREATED).body(service.storeCredential(data, identifier)); } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java index d2ae93564..d9bfebd6e 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/CreateWalletRequest.java @@ -32,15 +32,15 @@ @Getter @Setter @NoArgsConstructor -@Builder @AllArgsConstructor +@Builder public class CreateWalletRequest { - @NotBlank - @Size(min = 5, max = 255) + @NotBlank(message = "Please provide BPN") + @Size(min = 5, max = 255, message = "Please provide valid BPN") private String bpn; - @NotBlank - @Size(min = 5, max = 255) + @NotBlank(message = "Please provide name") + @Size(min = 1, max = 255, message = "Please provide valid name") private String name; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueDismantlerCredentialRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueDismantlerCredentialRequest.java new file mode 100644 index 000000000..29d9f312c --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueDismantlerCredentialRequest.java @@ -0,0 +1,51 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import lombok.*; + +import java.util.Set; + +/** + * The type Issue dismantler credential request. + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IssueDismantlerCredentialRequest { + + @NotBlank(message = "Please provide BPN") + @Size(min = 5, max = 255, message = "Please provide valid BPN") + private String bpn; + + @NotBlank(message = "Please provide activity type") + @Size(min = 1, message = "Please provide valid activity type") + private String activityType; + + @NotEmpty(message = "Please provide allowed vehicle brands") + private Set allowedVehicleBrands; +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueFrameworkCredentialRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueFrameworkCredentialRequest.java new file mode 100644 index 000000000..9090d76de --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueFrameworkCredentialRequest.java @@ -0,0 +1,60 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.*; + + +/** + * The type Issue framework credential request. + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IssueFrameworkCredentialRequest { + + @NotBlank(message = "Please provide BPN") + @Size(min = 5, max = 255, message = "Please provide valid BPN") + private String bpn; + + @NotBlank(message = "Please provide value") + @Pattern(regexp = "Behavior Twin|PCF|Quality|Resiliency|Sustainability|ID_3.0_Trace", message = "Invalid value, possible values are Behavior Twin, PCF, Quality, Resiliency, Sustainability, ID_3.0_Trace") + private String value; + + @NotBlank(message = "Please provide type") + @Pattern(regexp = "cx-behavior-twin|cx-pcf|cx-quality|cx-resiliency|cx-sustainability|cx-traceability", message = "Invalid type, possible values are cx-behavior-twin, cx-pcf, cx-quality, cx-resiliency, cx-sustainability, cx-traceability") + private String type; + + @NotBlank(message = "Please provide contract-template") + @JsonProperty("contract-template") + private String contractTemplate; + + @NotBlank(message = "Please provide contract-template") + @JsonProperty("contract-version") + private String contractVersion; +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java index e3a37df59..2fc001a21 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/dto/IssueMembershipCredentialRequest.java @@ -35,8 +35,8 @@ @AllArgsConstructor public class IssueMembershipCredentialRequest { - @NotBlank - @Size(min = 5, max = 255) + @NotBlank(message = "Please provide BPN") + @Size(min = 5, max = 255, message = "Please provide valid BPN") private String bpn; } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java index ea4b18a15..1ad5fe1f4 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/CredentialService.java @@ -26,11 +26,14 @@ import lombok.extern.slf4j.Slf4j; import org.bouncycastle.util.io.pem.PemReader; import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; +import org.eclipse.tractusx.managedidentitywallets.constant.MIWVerifiableCredentialType; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey; import org.eclipse.tractusx.managedidentitywallets.dao.repository.CredentialRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.exception.DuplicateCredentialProblem; import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils; @@ -78,6 +81,66 @@ public List getCredentials(String holderIdentifier, String id, Strin return credentialRepository.findAll();//TODO with params } + /** + * Issue framework credential verifiable credential. + * + * @param request the request + * @return the verifiable credential + */ + public VerifiableCredential issueFrameworkCredential(IssueFrameworkCredentialRequest request) { + //Fetch Holder Wallet + Wallet holderWallet = walletService.getWalletByIdentifier(request.getBpn()); + + // Fetch Issuer Wallet + Wallet baseWallet = walletService.getWalletByIdentifier(miwSettings.authorityWalletBpn()); + byte[] privateKeyBytes = getPrivateKeyById(baseWallet.getId()); + + Map subject = Map.of("type", request.getType(), + "id", holderWallet.getDid(), + "value", request.getValue(), + "contract-template", request.getContractTemplate(), + "contract-version", request.getContractVersion()); + Credential credential = getCredential(subject, MIWVerifiableCredentialType.USE_CASE_FRAMEWORK_CONDITION_CX, baseWallet, privateKeyBytes, holderWallet); + + //Store Credential + credentialRepository.save(credential); + + // Return VC + return credential.getData(); + } + + /** + * Issue dismantler credential verifiable credential. + * + * @param request the request + * @return the verifiable credential + */ + public VerifiableCredential issueDismantlerCredential(IssueDismantlerCredentialRequest request) { + + //Fetch Holder Wallet + Wallet holderWallet = walletService.getWalletByIdentifier(request.getBpn()); + + //check duplicate + isCredentialExit(holderWallet.getId(), MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL_CX); + + // Fetch Issuer Wallet + Wallet baseWallet = walletService.getWalletByIdentifier(miwSettings.authorityWalletBpn()); + byte[] privateKeyBytes = getPrivateKeyById(baseWallet.getId()); + + Map subject = Map.of("type", MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL_CX, + "id", holderWallet.getDid(), + "holderIdentifier", holderWallet.getBpn(), + "activityType", request.getActivityType(), + "allowedVehicleBrands", request.getAllowedVehicleBrands()); + Credential credential = getCredential(subject, MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL_CX, baseWallet, privateKeyBytes, holderWallet); + + //Store Credential + credentialRepository.save(credential); + + // Return VC + return credential.getData(); + } + /** * Issue membership credential verifiable credential. * @@ -98,26 +161,12 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR byte[] privateKeyBytes = getPrivateKeyById(baseWallet.getId()); //VC Subject - VerifiableCredentialSubject verifiableCredentialSubject = - new VerifiableCredentialSubject(Map.of("type", VerifiableCredentialType.MEMBERSHIP_CREDENTIAL, - "holderIdentifier", holderWallet.getBpn(), - "memberOf", baseWallet.getName(), - "status", "Active", - "startTime", Instant.now().toString())); - - // VC Type - List verifiableCredentialType = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); - - // Create VC - VerifiableCredential verifiableCredential = createVerifiableCredential(baseWallet.getDid(), verifiableCredentialType, verifiableCredentialSubject, privateKeyBytes); - - // Create Credential - Credential credential = Credential.builder() - .holder(holderWallet.getId()) - .issuer(baseWallet.getId()) - .type(VerifiableCredentialType.MEMBERSHIP_CREDENTIAL) - .data(verifiableCredential) - .build(); + Credential credential = getCredential(Map.of("type", VerifiableCredentialType.MEMBERSHIP_CREDENTIAL, + "id", holderWallet.getDid(), + "holderIdentifier", holderWallet.getBpn(), + "memberOf", baseWallet.getName(), + "status", "Active", + "startTime", Instant.now().toString()), VerifiableCredentialType.MEMBERSHIP_CREDENTIAL, baseWallet, privateKeyBytes, holderWallet); //Store Credential credentialRepository.save(credential); @@ -127,21 +176,21 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR } private VerifiableCredential createVerifiableCredential(String issuerDid, List verifiableCredentialType, VerifiableCredentialSubject verifiableCredentialSubject, byte[] privateKey) { - List context = List.of("https://www.w3.org/2018/credentials/v1", "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData"); //VC Builder VerifiableCredentialBuilder builder = new VerifiableCredentialBuilder() - .context(context) + .context(miwSettings.vcContexts()) .id(URI.create(UUID.randomUUID().toString())) .type(verifiableCredentialType) .issuer(URI.create(issuerDid)) - .expirationDate(Instant.now().plusSeconds(365 * 86400)) //TODO need to verify expiry time + .expirationDate(miwSettings.vcExpiryDate().toInstant()) .issuanceDate(Instant.now()) .credentialSubject(verifiableCredentialSubject); + //Ed25519 Proof Builder LinkedDataProofGenerator generator = LinkedDataProofGenerator.create(); - Ed25519Signature2020 proof = generator.createEd25519Signature2020(builder.build(), URI.create(issuerDid + "#key-1"), privateKey); + Ed25519Signature2020 proof = generator.createEd25519Signature2020(builder.build(), URI.create(issuerDid), privateKey); //Adding Proof to VC builder.proof(proof); @@ -150,6 +199,28 @@ private VerifiableCredential createVerifiableCredential(String issuerDid, List subject, String type, Wallet baseWallet, byte[] privateKeyBytes, Wallet holderWallet) { + //VC Subject + VerifiableCredentialSubject verifiableCredentialSubject = + new VerifiableCredentialSubject(subject); + + // VC Type + List verifiableCredentialType = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, type); + + // Create VC + VerifiableCredential verifiableCredential = createVerifiableCredential(baseWallet.getDid(), verifiableCredentialType, verifiableCredentialSubject, privateKeyBytes); + + // Create Credential + return Credential.builder() + .holder(holderWallet.getId()) + .issuer(baseWallet.getId()) + .type(type) + .data(verifiableCredential) + .build(); + } + + @SneakyThrows private byte[] getPrivateKeyById(Long id) { WalletKey baseWalletKey = walletKeyRepository.getByWalletId(id); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java index f208df6f9..57a58cde3 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/CommonUtils.java @@ -28,6 +28,10 @@ */ public class CommonUtils { + private CommonUtils() { + throw new IllegalStateException("Utility class"); + } + /** * Gets identifier type. * diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionUtils.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionUtils.java index 440aabd78..583e9421f 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionUtils.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionUtils.java @@ -36,7 +36,6 @@ @Component public class EncryptionUtils { - private final Cipher cipher; private final Key aesKey; /** @@ -47,8 +46,6 @@ public class EncryptionUtils { @SneakyThrows public EncryptionUtils(MIWSettings miwSettings) { aesKey = new SecretKeySpec(miwSettings.encryptionKey().getBytes(), "AES"); - cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, aesKey); } @@ -60,8 +57,10 @@ public EncryptionUtils(MIWSettings miwSettings) { */ @SneakyThrows public String encrypt(String text){ + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, aesKey); byte[] encrypted = cipher.doFinal(text.getBytes()); - return Base64.getEncoder().encodeToString(encrypted); + return Base64.getEncoder().encodeToString(encrypted); } /** @@ -72,6 +71,7 @@ public String encrypt(String text){ */ @SneakyThrows public String decrypt(String text){ + Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, aesKey); return new String(cipher.doFinal(Base64.getDecoder().decode(text))); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0e1f0c38b..3739e374d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -64,6 +64,8 @@ miw: encryptionKey: ${ENCRYPTION_KEY:Woh9waid4Ei5eez0aitieghoow9so4oe} authorityWalletBpn: ${AUTHORITY_WALLET_BPN:BPNL000000000000} authorityWalletName: ${AUTHORITY_WALLET_NAME:Catena-X} + vcContexts: ${VC_SCHEMA_LINK:https://www.w3.org/2018/credentials/v1, https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData} + vcExpiryDate: ${VC_EXPIRY_DATE:01-01-2025} #dd-MM-yyyy ie. 01-01-2025 expiry date will be 2024-12-31T18:30:00Z in VC security: enabled: true realm: ${KEYCLOAK_REALM:miw} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/DidDocumentsTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/did/DidDocumentsTest.java similarity index 80% rename from src/test/java/org/eclipse/tractusx/managedidentitywallets/DidDocumentsTest.java rename to src/test/java/org/eclipse/tractusx/managedidentitywallets/did/DidDocumentsTest.java index 2fd6eca82..982826118 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/DidDocumentsTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/did/DidDocumentsTest.java @@ -19,14 +19,18 @@ * ****************************************************************************** */ -package org.eclipse.tractusx.managedidentitywallets; +package org.eclipse.tractusx.managedidentitywallets.did; +import org.eclipse.tractusx.managedidentitywallets.ManagedIdentityWalletsApplication; import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.CredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -40,29 +44,39 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {ManagedIdentityWalletsApplication.class}) @ActiveProfiles("test") @ContextConfiguration(initializers = {TestContextInitializer.class}) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class DidDocumentsTest { @Autowired private WalletRepository walletRepository; + @Autowired - private TestRestTemplate restTemplate; + private WalletKeyRepository walletKeyRepository; + + @Autowired + private CredentialRepository credentialRepository; - private final String bpn = UUID.randomUUID().toString(); + @Autowired + private TestRestTemplate restTemplate; - private final String did = "did:web:localhost" + bpn; @Test - @Order(1) void getDidDocumentInvalidBpn404() { ResponseEntity response = restTemplate.getForEntity(RestURI.DID_DOCUMENTS, String.class, UUID.randomUUID().toString()); Assertions.assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatusCode().value()); } @Test - @Order(2) void getDidDocumentWithBpn200() { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + + createWallet(bpn, did); + ResponseEntity response = restTemplate.getForEntity(RestURI.DID_DOCUMENTS, String.class, bpn); + Assertions.assertEquals(HttpStatus.OK.value(), response.getStatusCode().value()); + Assertions.assertNotNull(response.getBody()); + } + + private Wallet createWallet(String bpn, String did) { String didDocument = """ { "id": "did:web:localhost%3Abpn123124", @@ -85,15 +99,15 @@ void getDidDocumentWithBpn200() { .algorithm("ED25519") .name(bpn) .build(); - walletRepository.save(wallet); - ResponseEntity response = restTemplate.getForEntity(RestURI.DID_DOCUMENTS, String.class, bpn); - Assertions.assertEquals(HttpStatus.OK.value(), response.getStatusCode().value()); - Assertions.assertNotNull(response.getBody()); + return walletRepository.save(wallet); } @Test - @Order(3) void getDidDocumentWithDid200() { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + + createWallet(bpn, did); ResponseEntity response = restTemplate.getForEntity(RestURI.DID_DOCUMENTS, String.class, did); Assertions.assertEquals(HttpStatus.OK.value(), response.getStatusCode().value()); Assertions.assertNotNull(response.getBody()); diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/AuthenticationUtils.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/AuthenticationUtils.java similarity index 96% rename from src/test/java/org/eclipse/tractusx/managedidentitywallets/AuthenticationUtils.java rename to src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/AuthenticationUtils.java index 5d3008741..c1115e8e6 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/AuthenticationUtils.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/AuthenticationUtils.java @@ -19,7 +19,7 @@ * ****************************************************************************** */ -package org.eclipse.tractusx.managedidentitywallets; +package org.eclipse.tractusx.managedidentitywallets.utils; import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; import org.jetbrains.annotations.NotNull; @@ -55,20 +55,6 @@ public static String getInvalidToken(){ return UUID.randomUUID().toString(); } - private static String getJwtToken(String username){ - Keycloak keycloakAdminClient = KeycloakBuilder.builder() - .serverUrl(TestContextInitializer.getAuthServerUrl()) - .realm(REALM) - .clientId(CLIENT_ID) - .clientSecret(CLIENT_SECRET) - .username(username) - .password(USER_PASSWORD) - .build(); - String access_token = keycloakAdminClient.tokenManager().getAccessToken().getToken(); - - return "Bearer " + access_token; - } - @NotNull public static HttpHeaders getInvalidUserHttpHeaders() { String token = AuthenticationUtils.getInvalidUserToken(); @@ -86,4 +72,19 @@ public static HttpHeaders getValidUserHttpHeaders() { return headers; } + + private static String getJwtToken(String username) { + Keycloak keycloakAdminClient = KeycloakBuilder.builder() + .serverUrl(TestContextInitializer.getAuthServerUrl()) + .realm(REALM) + .clientId(CLIENT_ID) + .clientSecret(CLIENT_SECRET) + .username(username) + .password(USER_PASSWORD) + .build(); + String access_token = keycloakAdminClient.tokenManager().getAccessToken().getToken(); + + return "Bearer " + access_token; + } + } diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionTest.java new file mode 100644 index 000000000..eac637b72 --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/EncryptionTest.java @@ -0,0 +1,49 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.utils; + +import org.eclipse.tractusx.managedidentitywallets.ManagedIdentityWalletsApplication; +import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {ManagedIdentityWalletsApplication.class}) +@ActiveProfiles("test") +@ContextConfiguration(initializers = {TestContextInitializer.class}) +public class EncryptionTest { + + @Autowired + private EncryptionUtils encryptionUtils; + + @Test + void encryptionTest() { + String originalMassage = "Dummy test message"; + String encrypt = encryptionUtils.encrypt(originalMassage); + String decrypt = encryptionUtils.decrypt(encrypt); + Assertions.assertEquals(originalMassage, decrypt); + } + +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java new file mode 100644 index 000000000..473ab5339 --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/TestUtils.java @@ -0,0 +1,69 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.utils; + +import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; +import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; +import org.junit.jupiter.api.Assertions; + +public class TestUtils { + + public static Wallet createWallet(String bpn, String did, WalletRepository walletRepository) { + String didDocument = """ + { + "id": "did:web:localhost:bpn123124", + "verificationMethod": [ + { + "publicKeyMultibase": "z9mo3TUPvEntiBQtHYVXXy5DfxLGgaHa84ZT6Er2qWs4y", + "controller": "did:web:localhost%3Abpn123124", + "id": "did:web:localhost%3Abpn123124#key-1", + "type": "Ed25519VerificationKey2020" + } + ], + "@context": "https://www.w3.org/ns/did/v1" + } + """; + + Wallet wallet = Wallet.builder() + .bpn(bpn) + .did(did) + .didDocument(DidDocument.fromJson(didDocument)) + .algorithm("ED25519") + .name(bpn) + .build(); + return walletRepository.save(wallet); + } + + public static void checkVC(VerifiableCredential verifiableCredential, MIWSettings miwSettings) { + //text context URL + Assertions.assertEquals(verifiableCredential.getContext().size(), miwSettings.vcContexts().size()); + for (String link : verifiableCredential.getContext()) { + Assertions.assertTrue(miwSettings.vcContexts().contains(link)); + } + + //check expiry date + Assertions.assertEquals(verifiableCredential.getExpirationDate().compareTo(miwSettings.vcExpiryDate().toInstant()), 0); + } +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/ValidateTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/ValidateTest.java similarity index 94% rename from src/test/java/org/eclipse/tractusx/managedidentitywallets/ValidateTest.java rename to src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/ValidateTest.java index 18321cb62..179e92a68 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/ValidateTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/utils/ValidateTest.java @@ -19,9 +19,8 @@ * ****************************************************************************** */ -package org.eclipse.tractusx.managedidentitywallets; +package org.eclipse.tractusx.managedidentitywallets.utils; -import org.eclipse.tractusx.managedidentitywallets.utils.Validate; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerCredentialTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerCredentialTest.java new file mode 100644 index 000000000..24adf6e0b --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/DismantlerCredentialTest.java @@ -0,0 +1,157 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.vc; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.tractusx.managedidentitywallets.ManagedIdentityWalletsApplication; +import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; +import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; +import org.eclipse.tractusx.managedidentitywallets.constant.MIWVerifiableCredentialType; +import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.CredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.utils.AuthenticationUtils; +import org.eclipse.tractusx.managedidentitywallets.utils.TestUtils; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; +import org.json.JSONException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {ManagedIdentityWalletsApplication.class}) +@ActiveProfiles("test") +@ContextConfiguration(initializers = {TestContextInitializer.class}) +public class DismantlerCredentialTest { + @Autowired + private CredentialRepository credentialRepository; + @Autowired + private WalletRepository walletRepository; + + @Autowired + private WalletKeyRepository walletKeyRepository; + + @Autowired + private TestRestTemplate restTemplate; + + @Autowired + private MIWSettings miwSettings; + + + @Test + void issueDismantlerCredentialTest403() { + String bpn = UUID.randomUUID().toString(); + + String did = "did:web:localhost:" + bpn; + HttpHeaders headers = AuthenticationUtils.getInvalidUserHttpHeaders(); + + IssueMembershipCredentialRequest request = IssueMembershipCredentialRequest.builder().bpn(bpn).build(); + + HttpEntity entity = new HttpEntity<>(request, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_DISMANTLER, HttpMethod.POST, entity, VerifiableCredential.class); + Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode().value()); + } + + + @Test + void issueDismantlerCredentialTest201() throws JsonProcessingException, JSONException { + + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:"+bpn; + + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + ResponseEntity response = issueDismantlerCredential(bpn, did); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(response.getBody(), Map.class); + VerifiableCredential verifiableCredential = new VerifiableCredential(map); + Assertions.assertTrue(verifiableCredential.getTypes().contains(MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL_CX)); + + TestUtils.checkVC(verifiableCredential, miwSettings); + + + Assertions.assertTrue(verifiableCredential.getCredentialSubject().get(0).get("activityType").toString().equals("vehicleDismantle")); + + Credential credential = credentialRepository.getByHolderAndType(wallet.getId(), MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL_CX); + Assertions.assertNotNull(credential); + TestUtils.checkVC(credential.getData(), miwSettings); + + + VerifiableCredential data = credential.getData(); + + Assertions.assertTrue(data.getCredentialSubject().get(0).get("activityType").toString().equals("vehicleDismantle")); + + } + + @Test + void issueDismantlerCredentialWithDuplicateBpn409() { + + String bpn = UUID.randomUUID().toString(); + + String did = "did:web:localhost:" + bpn; + + //create entry + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + ResponseEntity response = issueDismantlerCredential(bpn, did); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + //issue duplicate + ResponseEntity duplicateResponse = issueDismantlerCredential(bpn, did); + Assertions.assertEquals(HttpStatus.CONFLICT.value(), duplicateResponse.getStatusCode().value()); + } + + + + private ResponseEntity issueDismantlerCredential(String bpn, String did){ + + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueDismantlerCredentialRequest request = IssueDismantlerCredentialRequest.builder() + .activityType("vehicleDismantle") + .bpn(bpn) + .allowedVehicleBrands(Set.of("BMW")) + .build(); + + + HttpEntity entity = new HttpEntity<>(request, headers); + + return restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_DISMANTLER, HttpMethod.POST, entity, String.class); + } + +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkCredentialTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkCredentialTest.java new file mode 100644 index 000000000..71949a0e7 --- /dev/null +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/FrameworkCredentialTest.java @@ -0,0 +1,269 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2023 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.vc; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.tractusx.managedidentitywallets.ManagedIdentityWalletsApplication; +import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; +import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; +import org.eclipse.tractusx.managedidentitywallets.constant.MIWVerifiableCredentialType; +import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; +import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.CredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; +import org.eclipse.tractusx.managedidentitywallets.utils.AuthenticationUtils; +import org.eclipse.tractusx.managedidentitywallets.utils.TestUtils; +import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; +import org.json.JSONException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +import java.util.Map; +import java.util.UUID; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {ManagedIdentityWalletsApplication.class}) +@ActiveProfiles("test") +@ContextConfiguration(initializers = {TestContextInitializer.class}) +public class FrameworkCredentialTest { + @Autowired + private CredentialRepository credentialRepository; + @Autowired + private WalletRepository walletRepository; + + @Autowired + private WalletKeyRepository walletKeyRepository; + + @Autowired + private TestRestTemplate restTemplate; + + @Autowired + private MIWSettings miwSettings; + + + @Test + void issueFrameworkCredentialTest403() { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + HttpHeaders headers = AuthenticationUtils.getInvalidUserHttpHeaders(); + + IssueMembershipCredentialRequest request = IssueMembershipCredentialRequest.builder().bpn(bpn).build(); + + HttpEntity entity = new HttpEntity<>(request, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, VerifiableCredential.class); + Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode().value()); + } + + @Test + void issueBehaviorTwinCredentialTest201() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + String type ="cx-behavior-twin"; + String value ="Behavior Twin"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + validate(wallet, type, value, response, miwSettings); + } + + + @Test + void issuePCFCredentialTest201() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + String type ="cx-pcf"; + String value ="PCF"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + validate(wallet, type, value, response, miwSettings); + } + + @Test + void issueQualityCredentialTest201() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + String type ="cx-quality"; + String value ="Quality"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + validate(wallet, type, value, response, miwSettings); + } + + @Test + void issueResiliencyCredentialTest201() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + String type ="cx-resiliency"; + String value ="Resiliency"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + validate(wallet, type, value, response, miwSettings); + } + + @Test + void issueSustainabilityCredentialTest201() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + String type ="cx-sustainability"; + String value ="Sustainability"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + validate(wallet, type, value, response, miwSettings); + } + + + @Test + void issueTraceabilityCredentialTest201() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + String type ="cx-traceability"; + String value ="ID_3.0_Trace"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + validate(wallet, type, value, response, miwSettings); + } + + @Test + void issueFrameworkCredentialTest400() throws JsonProcessingException, JSONException { + String bpn = UUID.randomUUID().toString(); + String did = "did:web:localhost:" + bpn; + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + + String type ="cx-traceability1"; + String value ="ID_3.0_Trace1"; + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + IssueFrameworkCredentialRequest twinRequest = getIssueFrameworkCredentialRequest(bpn, type, value); + + HttpEntity entity = new HttpEntity<>(twinRequest, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.BAD_REQUEST.value(), response.getStatusCode().value()); + + } + + private void validate(Wallet wallet, String type, String value, ResponseEntity response, MIWSettings miwSettings) throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(response.getBody(), Map.class); + VerifiableCredential verifiableCredential = new VerifiableCredential(map); + Assertions.assertTrue(verifiableCredential.getTypes().contains(MIWVerifiableCredentialType.USE_CASE_FRAMEWORK_CONDITION_CX)); + + TestUtils.checkVC(verifiableCredential, miwSettings); + + Assertions.assertTrue(verifiableCredential.getCredentialSubject().get(0).get("type").equals(type)); + Assertions.assertTrue(verifiableCredential.getCredentialSubject().get(0).get("value").equals(value)); + Assertions.assertTrue(verifiableCredential.getCredentialSubject().get(0).get("id").equals(wallet.getDid())); + + Credential credential = credentialRepository.getByHolderAndType(wallet.getId(), MIWVerifiableCredentialType.USE_CASE_FRAMEWORK_CONDITION_CX); + Assertions.assertNotNull(credential); + + VerifiableCredential vcFromDB = credential.getData(); + TestUtils.checkVC(vcFromDB, miwSettings); + + Assertions.assertTrue(vcFromDB.getCredentialSubject().get(0).get("type").equals(type)); + Assertions.assertTrue(vcFromDB.getCredentialSubject().get(0).get("value").equals(value)); + Assertions.assertTrue(vcFromDB.getCredentialSubject().get(0).get("id").equals(wallet.getDid())); + } + + private static IssueFrameworkCredentialRequest getIssueFrameworkCredentialRequest(String bpn, String type, String value) { + IssueFrameworkCredentialRequest twinRequest = IssueFrameworkCredentialRequest.builder() + .contractTemplate("http://localhost") + .contractVersion("v1") + .type(type) + .value(value) + .bpn(bpn) + .build(); + return twinRequest; + } +} diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/MembershipCredentialTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/MembershipCredentialTest.java similarity index 70% rename from src/test/java/org/eclipse/tractusx/managedidentitywallets/MembershipCredentialTest.java rename to src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/MembershipCredentialTest.java index c1c0c0d99..95665b070 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/MembershipCredentialTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/MembershipCredentialTest.java @@ -19,22 +19,27 @@ * ****************************************************************************** */ -package org.eclipse.tractusx.managedidentitywallets; +package org.eclipse.tractusx.managedidentitywallets.vc; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.tractusx.managedidentitywallets.ManagedIdentityWalletsApplication; +import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Credential; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dao.repository.CredentialRepository; +import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; import org.eclipse.tractusx.managedidentitywallets.dto.IssueMembershipCredentialRequest; -import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; +import org.eclipse.tractusx.managedidentitywallets.utils.AuthenticationUtils; +import org.eclipse.tractusx.managedidentitywallets.utils.TestUtils; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredentialType; import org.json.JSONException; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -48,23 +53,27 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {ManagedIdentityWalletsApplication.class}) @ActiveProfiles("test") @ContextConfiguration(initializers = {TestContextInitializer.class}) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class MembershipCredentialTest { @Autowired private CredentialRepository credentialRepository; @Autowired private WalletRepository walletRepository; + + @Autowired + private WalletKeyRepository walletKeyRepository; @Autowired private TestRestTemplate restTemplate; - private final String bpn = UUID.randomUUID().toString(); + @Autowired + private MIWSettings miwSettings; - private final String did = "did:web:localhost" + bpn; @Test - @Order(1) void issueMembershipCredentialTest403() { + String bpn = UUID.randomUUID().toString(); + + String did = "did:web:localhost:" + bpn; + HttpHeaders headers = AuthenticationUtils.getInvalidUserHttpHeaders(); IssueMembershipCredentialRequest request = IssueMembershipCredentialRequest.builder().bpn(bpn).build(); @@ -75,61 +84,64 @@ void issueMembershipCredentialTest403() { Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode().value()); } + @Test - @Order(2) void issueMembershipCredentialTest201() throws JsonProcessingException, JSONException { - String didDocument = """ - { - "id": "did:web:localhost%3Abpn123124", - "verificationMethod": [ - { - "publicKeyMultibase": "z9mo3TUPvEntiBQtHYVXXy5DfxLGgaHa84ZT6Er2qWs4y", - "controller": "did:web:localhost%3Abpn123124", - "id": "did:web:localhost%3Abpn123124#key-1", - "type": "Ed25519VerificationKey2020" - } - ], - "@context": "https://www.w3.org/ns/did/v1" - } - """; - - Wallet wallet = Wallet.builder() - .bpn(bpn) - .did(did) - .didDocument(DidDocument.fromJson(didDocument)) - .algorithm("ED25519") - .name(bpn) - .build(); - wallet = walletRepository.save(wallet); + String bpn = UUID.randomUUID().toString(); - HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); - IssueMembershipCredentialRequest request = IssueMembershipCredentialRequest.builder().bpn(bpn).build(); - HttpEntity entity = new HttpEntity<>(request, headers); + String did = "did:web:localhost:" + bpn; + + //save wallet + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); - ResponseEntity response = restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, HttpMethod.POST, entity, String.class); + ResponseEntity response = issueMembershipVC(bpn, did); Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); ObjectMapper objectMapper = new ObjectMapper(); Map map = objectMapper.readValue(response.getBody(), Map.class); VerifiableCredential verifiableCredential = new VerifiableCredential(map); + + TestUtils.checkVC(verifiableCredential, miwSettings); + Assertions.assertTrue(verifiableCredential.getTypes().contains(VerifiableCredentialType.MEMBERSHIP_CREDENTIAL)); Assertions.assertEquals(verifiableCredential.getCredentialSubject().get(0).get("holderIdentifier"), bpn); Credential credential = credentialRepository.getByHolderAndType(wallet.getId(), VerifiableCredentialType.MEMBERSHIP_CREDENTIAL); Assertions.assertNotNull(credential); + TestUtils.checkVC(credential.getData(), miwSettings); } @Test - @Order(3) void issueMembershipCredentialWithDuplicateBpn409() { + + String bpn = UUID.randomUUID().toString(); + + String did = "did:web:localhost:" + bpn; + + //save wallet + Wallet wallet = TestUtils.createWallet(bpn, did, walletRepository); + + ResponseEntity response = issueMembershipVC(bpn, did); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); IssueMembershipCredentialRequest request = IssueMembershipCredentialRequest.builder().bpn(bpn).build(); HttpEntity entity = new HttpEntity<>(request, headers); - ResponseEntity response = restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, HttpMethod.POST, entity, String.class); - Assertions.assertEquals(HttpStatus.CONFLICT.value(), response.getStatusCode().value()); + ResponseEntity duplicateResponse = restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, HttpMethod.POST, entity, String.class); + Assertions.assertEquals(HttpStatus.CONFLICT.value(), duplicateResponse.getStatusCode().value()); } + private ResponseEntity issueMembershipVC(String bpn, String did) { + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + IssueMembershipCredentialRequest request = IssueMembershipCredentialRequest.builder().bpn(bpn).build(); + HttpEntity entity = new HttpEntity<>(request, headers); + + return restTemplate.exchange(RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, HttpMethod.POST, entity, String.class); + } + + } diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/WalletTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/wallet/WalletTest.java similarity index 71% rename from src/test/java/org/eclipse/tractusx/managedidentitywallets/WalletTest.java rename to src/test/java/org/eclipse/tractusx/managedidentitywallets/wallet/WalletTest.java index ab376292a..bb46a9b84 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/WalletTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/wallet/WalletTest.java @@ -19,10 +19,11 @@ * ****************************************************************************** */ -package org.eclipse.tractusx.managedidentitywallets; +package org.eclipse.tractusx.managedidentitywallets.wallet; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.tractusx.managedidentitywallets.ManagedIdentityWalletsApplication; import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings; import org.eclipse.tractusx.managedidentitywallets.config.TestContextInitializer; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; @@ -33,14 +34,16 @@ import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletKeyRepository; import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository; import org.eclipse.tractusx.managedidentitywallets.dto.CreateWalletRequest; -import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils; +import org.eclipse.tractusx.managedidentitywallets.utils.AuthenticationUtils; import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; -import org.jetbrains.annotations.NotNull; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -55,14 +58,9 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {ManagedIdentityWalletsApplication.class}) @ActiveProfiles("test") @ContextConfiguration(initializers = {TestContextInitializer.class}) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) class WalletTest { - private final String bpn = "123456789"; - - private final String name = "smartSense"; - + private final static Logger LOGGER = LoggerFactory.getLogger(WalletTest.class); @Autowired private WalletRepository walletRepository; @@ -73,9 +71,6 @@ class WalletTest { @Autowired private TestRestTemplate restTemplate; - @Autowired - private EncryptionUtils encryptionUtils; - @Autowired private MIWSettings miwSettings; @@ -95,18 +90,11 @@ void authorityWalletExistTest() { Assertions.assertNotNull(wallet.getDidDocument()); } - @Test - void encryptionTest() { - String originalMassage = "Dummy test message"; - String encrypt = encryptionUtils.encrypt(originalMassage); - String decrypt = encryptionUtils.decrypt(encrypt); - Assertions.assertEquals(originalMassage, decrypt); - } - @Test - @Order(1) void createWalletTest403() { + String bpn = UUID.randomUUID().toString(); + String name = "Sample Wallet"; HttpHeaders headers = AuthenticationUtils.getInvalidUserHttpHeaders(); CreateWalletRequest request = CreateWalletRequest.builder().bpn(bpn).name(name).build(); @@ -117,90 +105,44 @@ void createWalletTest403() { Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode().value()); } + @Test - @Order(2) void createWalletTest201() throws JsonProcessingException, JSONException { - HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); - - CreateWalletRequest request = CreateWalletRequest.builder().bpn(bpn).name(name).build(); - - HttpEntity entity = new HttpEntity<>(request, headers); - - ResponseEntity response = restTemplate.exchange(RestURI.WALLETS, HttpMethod.POST, entity, String.class); - String body = response.getBody(); + String bpn = UUID.randomUUID().toString(); + String name = "Sample Wallet"; - Wallet wallet1 = getWalletFromString(body); + ResponseEntity response = createWallet(bpn, name); + Wallet wallet = getWalletFromString(response.getBody()); Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); Assertions.assertNotNull(response.getBody()); - Assertions.assertNotNull(wallet1.getDidDocument()); - Assertions.assertEquals(wallet1.getBpn(), bpn); - Assertions.assertEquals(wallet1.getName(), name); - - Wallet wallet = walletRepository.getByBpn(bpn); + Assertions.assertNotNull(wallet.getDidDocument()); Assertions.assertEquals(wallet.getBpn(), bpn); Assertions.assertEquals(wallet.getName(), name); - Assertions.assertNotNull(wallet); - WalletKey walletKey = walletKeyRepository.getByWalletId(wallet.getId()); - Assertions.assertNotNull(wallet1.getDidDocument()); + + Wallet walletFromDB = walletRepository.getByBpn(bpn); + Assertions.assertEquals(walletFromDB.getBpn(), bpn); + Assertions.assertEquals(walletFromDB.getName(), name); + Assertions.assertNotNull(walletFromDB); + WalletKey walletKey = walletKeyRepository.getByWalletId(walletFromDB.getId()); + Assertions.assertNotNull(wallet.getDidDocument()); Assertions.assertNotNull(walletKey); - Assertions.assertEquals(wallet.getBpn(), bpn); + Assertions.assertEquals(walletFromDB.getBpn(), bpn); } @Test - @Order(3) void storeCredentialsTest201() throws JsonProcessingException { - HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); - String vc = """ - { - "id": "http://example.edu/credentials/3732", - "@context": - [ - "https://www.w3.org/2018/credentials/v1", - "https://www.w3.org/2018/credentials/examples/v1" - ], - "type": - [ - "University-Degree-Credential", "VerifiableCredential" - ], - "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", - "issuanceDate": "2019-06-16T18:56:59Z", - "expirationDate": "2019-06-17T18:56:59Z", - "credentialSubject": - [ - { - "id": "did:web:localhost:BPNL000000000000", - "college": "Test-University" - } - ], - "credentialStatus": - { - "id": "http://example.edu/api/credentials/status/test#3", - "type": "StatusList2021Entry", - "statusPurpose": "revocation", - "statusListIndex": "3", - "statusListCredential": "http://example.edu/api/credentials/status/test" - }, - "proof": - { - "type": "Ed25519Signature2018", - "created": "2021-11-17T22:20:27Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:example:76e12ec712ebc6f1c221ebfeb1f#key-1", - "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..JNerzfrK46Mq4XxYZEnY9xOK80xsEaWCLAHuZsFie1-NTJD17wWWENn_DAlA_OwxGF5dhxUJ05P6Dm8lcmF5Cg" - } - } - """; - Map map = objectMapper.readValue(vc, Map.class); - HttpEntity entity = new HttpEntity<>(map, headers); + //make sure authority wallet is created + authorityWalletExistTest(); + String did = "did:web:localhost:" + miwSettings.authorityWalletBpn(); - ResponseEntity response = restTemplate.exchange(RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, HttpMethod.POST, entity, Map.class, miwSettings.authorityWalletBpn()); + ResponseEntity response = storeCredential(miwSettings.authorityWalletBpn(), did); Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); Wallet byBpn = walletRepository.getByBpn(miwSettings.authorityWalletBpn()); List byHolder = credentialRepository.getByHolder(byBpn.getId()); @@ -209,21 +151,35 @@ void storeCredentialsTest201() throws JsonProcessingException { } @Test - @Order(4) - void createWalletWithDuplicateBpn409() { - HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + void storeCredentialsWithDifferentHolder403() throws JsonProcessingException { + //make sure authority wallet is created + authorityWalletExistTest(); + String did = "did:web:localhost:" + miwSettings.authorityWalletBpn(); + ResponseEntity response = storeCredential(miwSettings.authorityWalletBpn(), "Some Random bpn"); + Assertions.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode().value()); - CreateWalletRequest request = CreateWalletRequest.builder().bpn(bpn).name(name).build(); - HttpEntity entity = new HttpEntity<>(request, headers); + } - ResponseEntity response = restTemplate.exchange(RestURI.WALLETS, HttpMethod.POST, entity, Wallet.class); - Assertions.assertEquals(HttpStatus.CONFLICT.value(), response.getStatusCode().value()); + @Test + void createWalletWithDuplicateBpn409() throws JsonProcessingException { + + String bpn = UUID.randomUUID().toString(); + String name = "Sample Wallet"; + + //save wallet + ResponseEntity response = createWallet(bpn, name); + getWalletFromString(response.getBody()); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + + //try with again with same BPN + ResponseEntity response1 = createWallet(bpn, name); + Assertions.assertEquals(HttpStatus.CONFLICT.value(), response1.getStatusCode().value()); } @Test - @Order(5) void getWalletByIdentifierTest403() { + String bpn = UUID.randomUUID().toString(); HttpHeaders headers = AuthenticationUtils.getInvalidUserHttpHeaders(); HttpEntity entity = new HttpEntity<>(headers); @@ -235,43 +191,64 @@ void getWalletByIdentifierTest403() { @Test - @Order(6) void getWalletByIdentifierBPNTest200() throws JsonProcessingException { + String bpn = UUID.randomUUID().toString(); + String name = "Sample Name"; + //Create entry + Wallet wallet = getWalletFromString(createWallet(bpn, name).getBody()); + + //get Wallet + ///get wallet with credentials HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity response = restTemplate.exchange(RestURI.API_WALLETS_IDENTIFIER, HttpMethod.GET, entity, String.class, bpn); + ResponseEntity getWalletResponse = restTemplate.exchange(RestURI.API_WALLETS_IDENTIFIER + "?withCredentials={withCredentials}", HttpMethod.GET, entity, String.class, bpn, "false"); - Wallet body = getWalletFromString(response.getBody()); - Assertions.assertEquals(HttpStatus.OK.value(), response.getStatusCode().value()); - Assertions.assertNotNull(response.getBody()); + Wallet body = getWalletFromString(getWalletResponse.getBody()); + Assertions.assertEquals(HttpStatus.OK.value(), getWalletResponse.getStatusCode().value()); + Assertions.assertNotNull(getWalletResponse.getBody()); Assertions.assertEquals(body.getBpn(), bpn); } @Test - @Order(7) void getWalletByIdentifierBPNWithCredentialsTest200() throws JsonProcessingException { + String bpn = UUID.randomUUID().toString(); + String name = "Sample Name"; + String did = "did:web:localhost:" + bpn; + //Create entry + Wallet wallet = getWalletFromString(createWallet(bpn, name).getBody()); + + //store credentials + ResponseEntity response = storeCredential(bpn, did); + Assertions.assertEquals(HttpStatus.CREATED.value(), response.getStatusCode().value()); + ///get wallet with credentials HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity response = restTemplate.exchange(RestURI.API_WALLETS_IDENTIFIER + "?withCredentials={withCredentials}", HttpMethod.GET, entity, String.class, miwSettings.authorityWalletBpn(), "true"); + ResponseEntity getWalletResponse = restTemplate.exchange(RestURI.API_WALLETS_IDENTIFIER + "?withCredentials={withCredentials}", HttpMethod.GET, entity, String.class, bpn, "true"); - Wallet body = getWalletFromString(response.getBody()); - Assertions.assertEquals(HttpStatus.OK.value(), response.getStatusCode().value()); - Assertions.assertNotNull(response.getBody()); + Wallet body = getWalletFromString(getWalletResponse.getBody()); + Assertions.assertEquals(HttpStatus.OK.value(), getWalletResponse.getStatusCode().value()); + Assertions.assertNotNull(getWalletResponse.getBody()); Assertions.assertEquals(1, body.getVerifiableCredentials().size()); - Assertions.assertEquals(body.getBpn(), miwSettings.authorityWalletBpn()); + Assertions.assertEquals(body.getBpn(), bpn); } - @Test - @Order(8) void getWalletByIdentifierDidTest200() throws JsonProcessingException { + + String bpn = UUID.randomUUID().toString(); + String name = "Sample Name"; + String did = "did:web:localhost:" + bpn; + + //Create entry + Wallet wallet = getWalletFromString(createWallet(bpn, name).getBody()); + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); HttpEntity entity = new HttpEntity<>(headers); Wallet newWallet = walletRepository.getByBpn(bpn); @@ -286,7 +263,6 @@ void getWalletByIdentifierDidTest200() throws JsonProcessingException { @Test - @Order(9) void getWalletInvalidBpn404() { HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); @@ -298,7 +274,6 @@ void getWalletInvalidBpn404() { } @Test - @Order(10) void getWallets403() { HttpHeaders headers = AuthenticationUtils.getInvalidUserHttpHeaders(); @@ -311,8 +286,14 @@ void getWallets403() { @Test - @Order(11) void getWallets200() throws JsonProcessingException { + + String bpn = UUID.randomUUID().toString(); + String name = "Sample Name"; + String did = "did:web:localhost:" + bpn; + //Create entry + createWallet(bpn, name); + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); HttpEntity entity = new HttpEntity<>(headers); ResponseEntity response = restTemplate.exchange(RestURI.WALLETS, HttpMethod.GET, entity, String.class); @@ -321,25 +302,10 @@ void getWallets200() throws JsonProcessingException { Assertions.assertTrue(Objects.requireNonNull(body).size() > 0); } - private static List getWalletsFromString(String body) throws JsonProcessingException { - List walletList = new ArrayList<>(); - JSONArray array = new JSONArray(body); - if (array.length() == 0) { - return walletList; - } - - for (int i = 0; i < array.length(); i++) { - JSONObject wallet = array.getJSONObject(i); - walletList.add(getWalletFromString(wallet.toString())); - } - return walletList; - } - - - @NotNull - private static Wallet getWalletFromString(String body) throws JsonProcessingException { + private Wallet getWalletFromString(String body) throws JsonProcessingException { JSONObject jsonObject = new JSONObject(body); - + LOGGER.info("-----------String body ->{}", body); + LOGGER.info("--------Json --->{}", jsonObject); //convert DidDocument JSONObject didDocument = jsonObject.getJSONObject("didDocument"); jsonObject.remove("didDocument"); @@ -366,4 +332,83 @@ private static Wallet getWalletFromString(String body) throws JsonProcessingExce System.out.println("wallet -- >" + wallet1.getBpn()); return wallet1; } + + + private ResponseEntity storeCredential(String bpn, String did) throws JsonProcessingException { + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + String vc = """ + { + "id": "http://example.edu/credentials/3732", + "@context": + [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "type": + [ + "University-Degree-Credential", "VerifiableCredential" + ], + "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", + "issuanceDate": "2019-06-16T18:56:59Z", + "expirationDate": "2019-06-17T18:56:59Z", + "credentialSubject": + [ + { + "id": "##did", + "college": "Test-University" + } + ], + "credentialStatus": + { + "id": "http://example.edu/api/credentials/status/test#3", + "type": "StatusList2021Entry", + "statusPurpose": "revocation", + "statusListIndex": "3", + "statusListCredential": "http://example.edu/api/credentials/status/test" + }, + "proof": + { + "type": "Ed25519Signature2018", + "created": "2021-11-17T22:20:27Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:example:76e12ec712ebc6f1c221ebfeb1f#key-1", + "jws": "eyJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJhbGciOiJFZERTQSJ9..JNerzfrK46Mq4XxYZEnY9xOK80xsEaWCLAHuZsFie1-NTJD17wWWENn_DAlA_OwxGF5dhxUJ05P6Dm8lcmF5Cg" + } + } + """; + + Map map = objectMapper.readValue(vc.replace("##did", did), Map.class); + HttpEntity entity = new HttpEntity<>(map, headers); + + ResponseEntity response = restTemplate.exchange(RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, HttpMethod.POST, entity, Map.class, bpn); + return response; + } + + + private ResponseEntity createWallet(String bpn, String name) { + HttpHeaders headers = AuthenticationUtils.getValidUserHttpHeaders(); + + CreateWalletRequest request = CreateWalletRequest.builder().bpn(bpn).name(name).build(); + + HttpEntity entity = new HttpEntity<>(request, headers); + + return restTemplate.exchange(RestURI.WALLETS, HttpMethod.POST, entity, String.class); + + } + + + private List getWalletsFromString(String body) throws JsonProcessingException { + List walletList = new ArrayList<>(); + JSONArray array = new JSONArray(body); + if (array.length() == 0) { + return walletList; + } + + for (int i = 0; i < array.length(); i++) { + JSONObject wallet = array.getJSONObject(i); + walletList.add(getWalletFromString(wallet.toString())); + } + return walletList; + } + }