-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
05f8e23
commit 7c5e2e2
Showing
14 changed files
with
515 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
196 changes: 196 additions & 0 deletions
196
...i/src/test/java/org/eclipse/edc/identityservice/api/v1/PresentationApiControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
/* | ||
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
* | ||
* 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 | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Contributors: | ||
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation | ||
* | ||
*/ | ||
|
||
package org.eclipse.edc.identityservice.api.v1; | ||
|
||
import com.nimbusds.jwt.JWTClaimsSet; | ||
import jakarta.json.JsonObject; | ||
import org.eclipse.edc.identityhub.spi.generator.PresentationGenerator; | ||
import org.eclipse.edc.identityhub.spi.model.InputDescriptorMapping; | ||
import org.eclipse.edc.identityhub.spi.model.PresentationQuery; | ||
import org.eclipse.edc.identityhub.spi.model.PresentationResponse; | ||
import org.eclipse.edc.identityhub.spi.model.PresentationSubmission; | ||
import org.eclipse.edc.identityhub.spi.model.presentationdefinition.PresentationDefinition; | ||
import org.eclipse.edc.identityhub.spi.resolution.CredentialQueryResolver; | ||
import org.eclipse.edc.identityhub.spi.verification.AccessTokenVerifier; | ||
import org.eclipse.edc.spi.EdcException; | ||
import org.eclipse.edc.spi.result.Result; | ||
import org.eclipse.edc.transform.spi.TypeTransformerRegistry; | ||
import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; | ||
import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; | ||
import org.eclipse.edc.web.spi.ApiErrorDetail; | ||
import org.eclipse.edc.web.spi.exception.AuthenticationFailedException; | ||
import org.eclipse.edc.web.spi.exception.InvalidRequestException; | ||
import org.eclipse.edc.web.spi.exception.NotAuthorizedException; | ||
import org.eclipse.edc.web.spi.exception.ValidationFailureException; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.sql.Date; | ||
import java.time.Instant; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
import static jakarta.json.Json.createObjectBuilder; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
import static org.eclipse.edc.identityhub.junit.testfixtures.VerifiableCredentialTestUtil.buildSignedJwt; | ||
import static org.eclipse.edc.identityhub.junit.testfixtures.VerifiableCredentialTestUtil.generateEcKey; | ||
import static org.eclipse.edc.identityhub.spi.model.PresentationQuery.PRESENTATION_QUERY_TYPE_PROPERTY; | ||
import static org.eclipse.edc.validator.spi.ValidationResult.failure; | ||
import static org.eclipse.edc.validator.spi.ValidationResult.success; | ||
import static org.eclipse.edc.validator.spi.Violation.violation; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.anyList; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.ArgumentMatchers.eq; | ||
import static org.mockito.ArgumentMatchers.isA; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.verifyNoInteractions; | ||
import static org.mockito.Mockito.when; | ||
|
||
@SuppressWarnings("resource") | ||
class PresentationApiControllerTest extends RestControllerTestBase { | ||
|
||
private final JsonObjectValidatorRegistry validatorRegistryMock = mock(); | ||
private final TypeTransformerRegistry typeTransformerRegistry = mock(); | ||
private final CredentialQueryResolver queryResolver = mock(); | ||
private final AccessTokenVerifier accessTokenVerifier = mock(); | ||
private final PresentationGenerator generator = mock(); | ||
|
||
|
||
@Test | ||
void query_tokenNotPresent_shouldReturn401() { | ||
assertThatThrownBy(() -> controller().queryPresentation(null, createObjectBuilder().build())) | ||
.isInstanceOf(AuthenticationFailedException.class) | ||
.hasMessage("Authorization header missing"); | ||
} | ||
|
||
@Test | ||
void query_validationError_shouldReturn400() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(failure(violation("foo", "bar"))); | ||
|
||
assertThatThrownBy(() -> controller().queryPresentation(generateJwt(), createObjectBuilder().build())) | ||
.isInstanceOf(ValidationFailureException.class) | ||
.hasMessage("foo"); | ||
} | ||
|
||
@Test | ||
void query_transformationError_shouldReturn400() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(success()); | ||
when(typeTransformerRegistry.transform(isA(JsonObject.class), eq(PresentationQuery.class))).thenReturn(Result.failure("cannot transform")); | ||
|
||
assertThatThrownBy(() -> controller().queryPresentation(generateJwt(), createObjectBuilder().build())) | ||
.isInstanceOf(InvalidRequestException.class) | ||
.hasMessage("cannot transform"); | ||
verifyNoInteractions(accessTokenVerifier, queryResolver, generator); | ||
} | ||
|
||
@Test | ||
void query_withPresentationDefinition_shouldReturn501() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(success()); | ||
var presentationQueryBuilder = createPresentationQueryBuilder() | ||
.presentationDefinition(PresentationDefinition.Builder.newInstance().id(UUID.randomUUID().toString()).build()); | ||
when(typeTransformerRegistry.transform(isA(JsonObject.class), eq(PresentationQuery.class))).thenReturn(Result.success(presentationQueryBuilder.build())); | ||
|
||
var response = controller().queryPresentation(generateJwt(), createObjectBuilder().build()); | ||
assertThat(response.getStatus()).isEqualTo(503); | ||
assertThat(response.getEntity()).extracting(o -> (ApiErrorDetail) o).satisfies(ed -> { | ||
assertThat(ed.getMessage()).isEqualTo("Not implemented."); | ||
assertThat(ed.getType()).isEqualTo("Not implemented."); | ||
}); | ||
verifyNoInteractions(accessTokenVerifier, queryResolver, generator); | ||
} | ||
|
||
|
||
@Test | ||
void query_tokenVerificationFails_shouldReturn401() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(success()); | ||
var presentationQueryBuilder = createPresentationQueryBuilder().build(); | ||
when(typeTransformerRegistry.transform(isA(JsonObject.class), eq(PresentationQuery.class))).thenReturn(Result.success(presentationQueryBuilder)); | ||
when(accessTokenVerifier.verify(anyString())).thenReturn(Result.failure("test-failure")); | ||
|
||
assertThatThrownBy(() -> controller().queryPresentation(generateJwt(), createObjectBuilder().build())) | ||
.isExactlyInstanceOf(AuthenticationFailedException.class) | ||
.hasMessage("ID token verification failed: test-failure"); | ||
verifyNoInteractions(queryResolver, generator); | ||
} | ||
|
||
@Test | ||
void query_queryResolutionFails_shouldReturn403() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(success()); | ||
var presentationQueryBuilder = createPresentationQueryBuilder().build(); | ||
when(typeTransformerRegistry.transform(isA(JsonObject.class), eq(PresentationQuery.class))).thenReturn(Result.success(presentationQueryBuilder)); | ||
when(accessTokenVerifier.verify(anyString())).thenReturn(Result.success(List.of("test-scope1"))); | ||
when(queryResolver.query(any(), eq(List.of("test-scope1")))).thenReturn(Result.failure("test-failure")); | ||
|
||
assertThatThrownBy(() -> controller().queryPresentation(generateJwt(), createObjectBuilder().build())) | ||
.isInstanceOf(NotAuthorizedException.class) | ||
.hasMessage("test-failure"); | ||
verifyNoInteractions(generator); | ||
} | ||
|
||
@Test | ||
void query_presentationGenerationFails_shouldReturn500() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(success()); | ||
var presentationQueryBuilder = createPresentationQueryBuilder().build(); | ||
when(typeTransformerRegistry.transform(isA(JsonObject.class), eq(PresentationQuery.class))).thenReturn(Result.success(presentationQueryBuilder)); | ||
when(accessTokenVerifier.verify(anyString())).thenReturn(Result.success(List.of("test-scope1"))); | ||
when(queryResolver.query(any(), eq(List.of("test-scope1")))).thenReturn(Result.success(List.of())); | ||
|
||
when(generator.createPresentation(anyList(), any())).thenReturn(Result.failure("test-failure")); | ||
|
||
assertThatThrownBy(() -> controller().queryPresentation(generateJwt(), createObjectBuilder().build())) | ||
.isExactlyInstanceOf(EdcException.class) | ||
.hasMessage("Error creating VerifiablePresentation: test-failure"); | ||
} | ||
|
||
@Test | ||
void query_success() { | ||
when(validatorRegistryMock.validate(eq(PRESENTATION_QUERY_TYPE_PROPERTY), any())).thenReturn(success()); | ||
var presentationQueryBuilder = createPresentationQueryBuilder().build(); | ||
when(typeTransformerRegistry.transform(isA(JsonObject.class), eq(PresentationQuery.class))).thenReturn(Result.success(presentationQueryBuilder)); | ||
when(accessTokenVerifier.verify(anyString())).thenReturn(Result.success(List.of("test-scope1"))); | ||
when(queryResolver.query(any(), eq(List.of("test-scope1")))).thenReturn(Result.success(List.of())); | ||
|
||
var pres = new PresentationResponse(generateJwt(), new PresentationSubmission("id", "def-id", List.of(new InputDescriptorMapping("id", "ldp_vp", "$.verifiableCredentials[0]")))); | ||
when(generator.createPresentation(anyList(), any())).thenReturn(Result.success(pres)); | ||
|
||
var response = controller().queryPresentation(generateJwt(), createObjectBuilder().build()); | ||
assertThat(response).isNotNull(); | ||
assertThat(response.getStatus()).isEqualTo(200); | ||
assertThat(response.getEntity()).isEqualTo(pres); | ||
|
||
} | ||
|
||
@Override | ||
protected PresentationApiController controller() { | ||
return new PresentationApiController(validatorRegistryMock, typeTransformerRegistry, queryResolver, accessTokenVerifier, generator, mock()); | ||
} | ||
|
||
private String generateJwt() { | ||
var ecKey = generateEcKey(); | ||
var jwt = buildSignedJwt(new JWTClaimsSet.Builder().audience("test-audience") | ||
.expirationTime(Date.from(Instant.now().plusSeconds(3600))) | ||
.issuer("test-issuer") | ||
.subject("test-subject") | ||
.jwtID(UUID.randomUUID().toString()).build(), ecKey); | ||
|
||
return jwt.serialize(); | ||
} | ||
|
||
private PresentationQuery.Builder createPresentationQueryBuilder() { | ||
return PresentationQuery.Builder.newinstance() | ||
.scopes(List.of("test-scope1", "test-scope2")); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.