Skip to content

Commit

Permalink
feat: delete credential api and test cases added
Browse files Browse the repository at this point in the history
  • Loading branch information
thackerronak committed Jun 6, 2023
1 parent 1d74e92 commit 3fbf420
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 67 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ configurations {
}

repositories {
mavenLocal()
// mavenLocal()
mavenCentral()
maven {
url = uri("https://repo.danubetech.com/repository/maven-public")
Expand Down Expand Up @@ -48,7 +48,7 @@ dependencies {
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:${openApiVersion}"
implementation group: 'com.smartsensesolutions', name: 'commons-dao', version: '0.0.5'
implementation 'org.liquibase:liquibase-core'
implementation 'org.eclipse.tractusx.ssi.lib:cx-ssi-lib:0.0.4'
implementation 'org.eclipse.tractusx.ssi:cx-ssi-lib:0.0.6'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ ProblemDetail handleDuplicateCredentialProblem(DuplicateCredentialProblem e) {
return problemDetail;
}

@ExceptionHandler(CredentialNotFoundProblem.class)
ProblemDetail handleNotFoundCredentialProblem(CredentialNotFoundProblem e) {
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());
problemDetail.setTitle(e.getMessage());
problemDetail.setProperty(TIMESTAMP, System.currentTimeMillis());
return problemDetail;
}

@ExceptionHandler(Exception.class)
ProblemDetail handleException(Exception e) {
log.error("Error ", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.*;

/**
* The type Security config.
Expand Down Expand Up @@ -89,6 +88,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
//VC - Holder
.requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS, GET.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //get credentials
.requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS, POST.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLET, ApplicationConstant.ROLE_UPDATE_WALLETS) //issue credentials
.requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS, DELETE.name())).hasAnyRole(ApplicationConstant.ROLE_UPDATE_WALLET) //delete credentials

//VC - validation
.requestMatchers(new AntPathRequestMatcher(RestURI.CREDENTIALS_VALIDATION, POST.name())).hasAnyRole(ApplicationConstant.ROLE_VIEW_WALLET, ApplicationConstant.ROLE_VIEW_WALLETS) //validate credentials
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,7 @@ public class MIWVerifiableCredentialType extends VerifiableCredentialType {
public static final String BPN_CREDENTIAL_CX = "BpnCredentialCX";

public static final String MEMBERSHIP_CREDENTIAL_CX = "MembershipCredentialCX";
public static final String SUMMARY_CREDENTIAL = "SummaryCredential";


}
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,11 @@ public ResponseEntity<List<VerifiableCredential>> getCredentials(@RequestParam(r
public ResponseEntity<VerifiableCredential> issueCredential(@RequestBody Map<String, Object> data, Principal principal) {
return ResponseEntity.status(HttpStatus.CREATED).body(holdersCredentialService.issueCredential(data, getBPNFromToken(principal)));
}

@Operation(description = "Permission: **update_wallet** (The BPN of holderIdentifier must equal BPN of caller)\n\n Delete a verifiable credential by its ID", summary = "Delete a verifiable credential by its ID")
@DeleteMapping(path = RestURI.CREDENTIALS, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> deleteCredential(@RequestParam(name = "id") String credentialId, Principal principal) {
holdersCredentialService.deleteCredential(credentialId, getBPNFromToken(principal));
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,14 @@ public class IssuersCredential extends MIWBaseEntity {

@Column(nullable = false)
private String credentialId;

public static IssuersCredential of(HoldersCredential holdersCredential) {
return IssuersCredential.builder()
.credentialId(holdersCredential.getCredentialId())
.data(holdersCredential.getData())
.type(holdersCredential.getType())
.issuerDid(holdersCredential.getIssuerDid())
.holderDid(holdersCredential.getHolderDid())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.smartsensesolutions.java.commons.base.repository.BaseRepository;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

Expand Down Expand Up @@ -67,4 +68,10 @@ public interface HoldersCredentialRepository extends BaseRepository<HoldersCrede
* @return the boolean
*/
boolean existsByHolderDidAndType(String holderDid, String type);

@Modifying
@Query("delete from HoldersCredential where credentialId=:credentialId")
void deleteByCredentialId(@Param("credentialId") String credentialId);

boolean existsByHolderDidAndCredentialId(String holderDid, String credentialId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* *******************************************************************************
* 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.exception;

/**
* The type Wallet not found problem.
*/
public class CredentialNotFoundProblem extends RuntimeException {

/**
* Instantiates a new Wallet not found problem.
*/
public CredentialNotFoundProblem() {
}

/**
* Instantiates a new Wallet not found problem.
*
* @param message the message
*/
public CredentialNotFoundProblem(String message) {
super(message);
}

/**
* Instantiates a new Wallet not found problem.
*
* @param message the message
* @param cause the cause
*/
public CredentialNotFoundProblem(String message, Throwable cause) {
super(message, cause);
}

/**
* Instantiates a new Wallet not found problem.
*
* @param cause the cause
*/
public CredentialNotFoundProblem(Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository;
import org.eclipse.tractusx.managedidentitywallets.exception.CredentialNotFoundProblem;
import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException;
import org.eclipse.tractusx.managedidentitywallets.utils.CommonUtils;
import org.eclipse.tractusx.managedidentitywallets.utils.Validate;
Expand All @@ -46,6 +47,9 @@
import org.eclipse.tractusx.ssi.lib.resolver.DidDocumentResolverRegistryImpl;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

Expand Down Expand Up @@ -212,4 +216,20 @@ public VerifiableCredential issueCredential(Map<String, Object> data, String cal
// Return VC
return credential.getData();
}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRED)
public void deleteCredential(String credentialId, String bpnFromToken) {
//Fetch Holder Wallet
Wallet holderWallet = walletService.getWalletByIdentifier(bpnFromToken);

//check credential exp
isCredentialExistWithId(holderWallet.getDid(), credentialId);

//remove credential
holdersCredentialRepository.deleteByCredentialId(credentialId);
}

private void isCredentialExistWithId(String holderDid, String credentialId) {
Validate.isFalse(holdersCredentialRepository.existsByHolderDidAndCredentialId(holderDid, credentialId)).launch(new CredentialNotFoundProblem("Credential ID: " + credentialId + " is not exists "));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,11 @@ public VerifiableCredential issueFrameworkCredential(IssueFrameworkCredentialReq
List<String> types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.USE_CASE_FRAMEWORK_CONDITION_CX);
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(subject, types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), false);

IssuersCredential issuersCredential = CommonUtils.getIssuersCredential(subject, types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate());

//save in holder wallet
holdersCredentialRepository.save(holdersCredential);
holdersCredential = holdersCredentialRepository.save(holdersCredential);

//Store Credential in issuers wallet table
//Store Credential in issuers table
IssuersCredential issuersCredential = IssuersCredential.of(holdersCredential);
issuersCredential = create(issuersCredential);

// Return VC
Expand Down Expand Up @@ -252,12 +251,12 @@ public VerifiableCredential issueDismantlerCredential(IssueDismantlerCredentialR
List<String> types = List.of(VerifiableCredentialType.VERIFIABLE_CREDENTIAL, MIWVerifiableCredentialType.DISMANTLER_CREDENTIAL_CX);
HoldersCredential holdersCredential = CommonUtils.getHoldersCredential(subject, types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), false);

IssuersCredential issuersCredential = CommonUtils.getIssuersCredential(subject, types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate());

//save in holder wallet
holdersCredentialRepository.save(holdersCredential);
holdersCredential = holdersCredentialRepository.save(holdersCredential);

//Store Credential in issuers wallet table
//Store Credential in issuers table
IssuersCredential issuersCredential = IssuersCredential.of(holdersCredential);
issuersCredential = create(issuersCredential);

// Return VC
Expand Down Expand Up @@ -296,17 +295,13 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR
"status", "Active",
"startTime", Instant.now().toString()), types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), false);

IssuersCredential issuersCredential = CommonUtils.getIssuersCredential(Map.of("type", VerifiableCredentialType.MEMBERSHIP_CREDENTIAL,
"id", holderWallet.getDid(),
"holderIdentifier", holderWallet.getBpn(),
"memberOf", baseWallet.getName(),
"status", "Active",
"startTime", Instant.now().toString()), types, baseWallet.getDidDocument(), privateKeyBytes, holderWallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate());

//save in holder wallet
holdersCredentialRepository.save(holdersCredential);
holdersCredential = holdersCredentialRepository.save(holdersCredential);

IssuersCredential issuersCredential = IssuersCredential.of(holdersCredential);

//Store Credential in holder table
//Store Credential in issuer table
issuersCredential = create(issuersCredential);

// Return VC
Expand All @@ -323,6 +318,7 @@ public VerifiableCredential issueMembershipCredential(IssueMembershipCredentialR
*/
public VerifiableCredential issueCredentialUsingBaseWallet(Map<String, Object> data, String callerBpn) {
VerifiableCredential verifiableCredential = new VerifiableCredential(data);

Wallet issuerWallet = walletService.getWalletByIdentifier(verifiableCredential.getIssuer().toString());

//validate BPN access, VC must be issued by base wallet
Expand All @@ -340,15 +336,12 @@ public VerifiableCredential issueCredentialUsingBaseWallet(Map<String, Object> d
privateKeyBytes, issuerWallet.getDid(),
verifiableCredential.getContext(), Date.from(verifiableCredential.getExpirationDate()), false);

IssuersCredential issuersCredential = CommonUtils.getIssuersCredential(verifiableCredential.getCredentialSubject().get(0),
verifiableCredential.getTypes(), issuerWallet.getDidDocument(),
privateKeyBytes, issuerWallet.getDid(),
verifiableCredential.getContext(), Date.from(verifiableCredential.getExpirationDate()));

//save in holder wallet
holdersCredentialRepository.save(holdersCredential);
holdersCredential = holdersCredentialRepository.save(holdersCredential);

//Store Credential in issuers table
IssuersCredential issuersCredential = IssuersCredential.of(holdersCredential);
issuersCredential = create(issuersCredential);

// Return VC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,11 @@ private Wallet createWallet(CreateWalletRequest request, boolean authority) {
"id", wallet.getDid(),
"bpn", wallet.getBpn()), types, baseWallet.getDidDocument(), privateKeyBytes, wallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate(), authority);

IssuersCredential issuersCredential = CommonUtils.getIssuersCredential(Map.of("type", MIWVerifiableCredentialType.BPN_CREDENTIAL,
"id", wallet.getDid(),
"bpn", wallet.getBpn()), types, baseWallet.getDidDocument(), privateKeyBytes, wallet.getDid(), miwSettings.vcContexts(), miwSettings.vcExpiryDate());

//Store Credential in holder wallet
holdersCredentialRepository.save(holdersCredential);
holdersCredential = holdersCredentialRepository.save(holdersCredential);

//save in issuers wallet
//Store Credential in issuers table
IssuersCredential issuersCredential = IssuersCredential.of(holdersCredential);
issuersCredentialRepository.save(issuersCredential);

log.debug("BPN credential issued for bpn -{}", request.getBpn());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import org.eclipse.tractusx.managedidentitywallets.constant.ApplicationConstant;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.IssuersCredential;
import org.eclipse.tractusx.ssi.lib.model.Ed25519Signature2020;
import org.eclipse.tractusx.ssi.lib.model.did.DidDocument;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential;
Expand Down Expand Up @@ -100,42 +99,6 @@ public static HoldersCredential getHoldersCredential(Map<String, Object> subject
}


/**
* Gets credential.
*
* @param subject the subject
* @param types the types
* @param issuerDoc the issuer doc
* @param privateKeyBytes the private key bytes
* @param holderDid the holder did
* @return the credential
*/
public static IssuersCredential getIssuersCredential(Map<String, Object> subject, List<String> types, DidDocument issuerDoc,
byte[] privateKeyBytes, String holderDid, List<String> contexts, Date expiryDate) {
//VC Subject
VerifiableCredentialSubject verifiableCredentialSubject =
new VerifiableCredentialSubject(subject);


List<String> cloneTypes = new ArrayList<>(types);

// Create VC
VerifiableCredential verifiableCredential = createVerifiableCredential(issuerDoc, types,
verifiableCredentialSubject, privateKeyBytes, contexts, expiryDate);

cloneTypes.remove(VerifiableCredentialType.VERIFIABLE_CREDENTIAL);

// Create Credential
return IssuersCredential.builder()
.holderDid(holderDid)
.issuerDid(issuerDoc.getId().toString())
.type(String.join(",", cloneTypes))
.credentialId(verifiableCredential.getId().toString())
.data(verifiableCredential)
.build();
}


private static VerifiableCredential createVerifiableCredential(DidDocument issuerDoc, List<String> verifiableCredentialType,
VerifiableCredentialSubject verifiableCredentialSubject,
byte[] privateKey, List<String> contexts, Date expiryDate) {
Expand Down
Loading

0 comments on commit 3fbf420

Please sign in to comment.