Skip to content

Commit

Permalink
Extension that merges authorize credential and signDocuments, since t…
Browse files Browse the repository at this point in the history
…he algorithm is now set in configuration
  • Loading branch information
vkanellopoulos committed Nov 11, 2024
1 parent afd90f2 commit 28aa266
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ sequenceDiagram
RQESService -->>- Client: RQESService.Authorized
Client ->>+ RQESService.Authorized: listCredentials(request)
RQESService.Authorized -->>- Client: List<CredentialInfo>
Client ->>+ RQESService.Authorized: getCredentialAuthorizationUrl(credential, documents)
Client ->>+ RQESService.Authorized: getCredentialAuthorizationUrl(credential, UnsignedDocuments)
RQESService.Authorized -->>- Client: HttpsUrl
Client ->>+ RQESService.Authorized: authorizeCredential(authorizationCode)
RQESService.Authorized -->>- Client: RQESService.CredentialAuthorized
Client ->>+ RQESService.CredentialAuthorized: signDocuments(algorithmOID)
Client ->>+ RQESService.CredentialAuthorized: signDocuments()
RQESService.CredentialAuthorized -->>- Client: SignedDocuments
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ class [AuthorizedImpl](index.md)(serverState: [String](https://kotlinlang.org/ap
| [authorizeCredential](authorize-credential.md) | [androidJvm]<br>open suspend override fun [authorizeCredential](authorize-credential.md)(authorizationCode: AuthorizationCode): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[RQESService.CredentialAuthorized](../../-r-q-e-s-service/-credential-authorized/index.md)&gt;<br>Authorize the credential. This method is used to authorize the credential that will be used to sign the documents. Once the authorizationCode is obtained using the credential authorization URL, it can be used to authorize the credential. The authorized credential can be used to sign the documents. |
| [getCredentialAuthorizationUrl](get-credential-authorization-url.md) | [androidJvm]<br>open suspend override fun [getCredentialAuthorizationUrl](get-credential-authorization-url.md)(credential: CredentialInfo, documents: [UnsignedDocuments](../../-unsigned-documents/index.md)): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;HttpsUrl&gt;<br>Get the credential authorization URL. This method is used to get the credential authorization URL. |
| [listCredentials](list-credentials.md) | [androidJvm]<br>open suspend override fun [listCredentials](list-credentials.md)(request: CredentialsListRequest?): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)&lt;CredentialInfo&gt;&gt;<br>List the credentials. This method is used to list the credentials. The credentials are the user's credentials that can be used to sign the documents. |
| [signDocuments](../../sign-documents.md) | [androidJvm]<br>suspend fun [RQESService.Authorized](../../-r-q-e-s-service/-authorized/index.md).[signDocuments](../../sign-documents.md)(authorizationCode: AuthorizationCode): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[SignedDocuments](../../-signed-documents/index.md)&gt;<br>Sign the documents with the given authorization code. |
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ The authorized service interface. This interface provides the methods to interac
| [authorizeCredential](authorize-credential.md) | [androidJvm]<br>abstract suspend fun [authorizeCredential](authorize-credential.md)(authorizationCode: AuthorizationCode): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[RQESService.CredentialAuthorized](../-credential-authorized/index.md)&gt;<br>Authorize the credential. This method is used to authorize the credential that will be used to sign the documents. Once the authorizationCode is obtained using the credential authorization URL, it can be used to authorize the credential. The authorized credential can be used to sign the documents. |
| [getCredentialAuthorizationUrl](get-credential-authorization-url.md) | [androidJvm]<br>abstract suspend fun [getCredentialAuthorizationUrl](get-credential-authorization-url.md)(credential: CredentialInfo, documents: [UnsignedDocuments](../../-unsigned-documents/index.md)): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;HttpsUrl&gt;<br>Get the credential authorization URL. This method is used to get the credential authorization URL. |
| [listCredentials](list-credentials.md) | [androidJvm]<br>abstract suspend fun [listCredentials](list-credentials.md)(request: CredentialsListRequest? = null): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)&lt;CredentialInfo&gt;&gt;<br>List the credentials. This method is used to list the credentials. The credentials are the user's credentials that can be used to sign the documents. |
| [signDocuments](../../sign-documents.md) | [androidJvm]<br>suspend fun [RQESService.Authorized](index.md).[signDocuments](../../sign-documents.md)(authorizationCode: AuthorizationCode): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[SignedDocuments](../../-signed-documents/index.md)&gt;<br>Sign the documents with the given authorization code. |
6 changes: 6 additions & 0 deletions docs/rqes-core/eu.europa.ec.eudi.rqes.core/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@
| [SignedDocuments](-signed-documents/index.md) | [androidJvm]<br>class [SignedDocuments](-signed-documents/index.md)(signedDocuments: [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)&lt;[InputStream](https://developer.android.com/reference/kotlin/java/io/InputStream.html)&gt;) : [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)&lt;[InputStream](https://developer.android.com/reference/kotlin/java/io/InputStream.html)&gt; <br>Represents a list of signed documents. |
| [UnsignedDocument](-unsigned-document/index.md) | [androidJvm]<br>data class [UnsignedDocument](-unsigned-document/index.md)(val label: [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html), val file: [File](https://developer.android.com/reference/kotlin/java/io/File.html), val signingConfig: [UnsignedDocument.Config](-unsigned-document/-config/index.md) = Config.DEFAULT)<br>Represents a document that is to be signed. |
| [UnsignedDocuments](-unsigned-documents/index.md) | [androidJvm]<br>class [UnsignedDocuments](-unsigned-documents/index.md)(unsignedDocuments: [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)&lt;[UnsignedDocument](-unsigned-document/index.md)&gt;) : [List](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html)&lt;[UnsignedDocument](-unsigned-document/index.md)&gt; <br>A list of [UnsignedDocument](-unsigned-document/index.md)s to be signed. |

## Functions

| Name | Summary |
|---|---|
| [signDocuments](sign-documents.md) | [androidJvm]<br>suspend fun [RQESService.Authorized](-r-q-e-s-service/-authorized/index.md).[signDocuments](sign-documents.md)(authorizationCode: AuthorizationCode): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[SignedDocuments](-signed-documents/index.md)&gt;<br>Sign the documents with the given authorization code. |
22 changes: 22 additions & 0 deletions docs/rqes-core/eu.europa.ec.eudi.rqes.core/sign-documents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//[rqes-core](../../index.md)/[eu.europa.ec.eudi.rqes.core](index.md)/[signDocuments](sign-documents.md)

# signDocuments

[androidJvm]\
suspend fun [RQESService.Authorized](-r-q-e-s-service/-authorized/index.md).[signDocuments](sign-documents.md)(authorizationCode: AuthorizationCode): [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html)&lt;[SignedDocuments](-signed-documents/index.md)&gt;

Sign the documents with the given authorization code.

Extension function for [RQESService.Authorized](-r-q-e-s-service/-authorized/index.md) that merges the authorization and signing of the documents.

#### Return

The signed documents

#### Parameters

androidJvm

| | |
|---|---|
| authorizationCode | The authorization code |
1 change: 1 addition & 0 deletions docs/rqes-core/package-list
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$dokka.format:gfm-v1
$dokka.linkExtension:md
$dokka.location:eu.europa.ec.eudi.rqes.core////PointingToDeclaration/rqes-core/eu.europa.ec.eudi.rqes.core/index.md
$dokka.location:eu.europa.ec.eudi.rqes.core//signDocuments/eu.europa.ec.eudi.rqes.core.RQESService.Authorized#eu.europa.ec.eudi.rqes.AuthorizationCode/PointingToDeclaration/rqes-core/eu.europa.ec.eudi.rqes.core/sign-documents.md
$dokka.location:eu.europa.ec.eudi.rqes.core/RQESService.Authorized///PointingToDeclaration/rqes-core/eu.europa.ec.eudi.rqes.core/-r-q-e-s-service/-authorized/index.md
$dokka.location:eu.europa.ec.eudi.rqes.core/RQESService.Authorized/authorizeCredential/#eu.europa.ec.eudi.rqes.AuthorizationCode/PointingToDeclaration/rqes-core/eu.europa.ec.eudi.rqes.core/-r-q-e-s-service/-authorized/authorize-credential.md
$dokka.location:eu.europa.ec.eudi.rqes.core/RQESService.Authorized/getCredentialAuthorizationUrl/#eu.europa.ec.eudi.rqes.CredentialInfo#eu.europa.ec.eudi.rqes.core.UnsignedDocuments/PointingToDeclaration/rqes-core/eu.europa.ec.eudi.rqes.core/-r-q-e-s-service/-authorized/get-credential-authorization-url.md
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://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.
*/

package eu.europa.ec.eudi.rqes.core

import eu.europa.ec.eudi.rqes.AuthorizationCode

/**
* Sign the documents with the given authorization code.
*
* Extension function for [RQESService.Authorized] that merges the authorization and signing of
* the documents.
*
* @param authorizationCode The authorization code
* @return The signed documents
*/
suspend fun RQESService.Authorized.signDocuments(
authorizationCode: AuthorizationCode
): Result<SignedDocuments> = this.authorizeCredential(authorizationCode)
.mapCatching { it.signDocuments().getOrThrow() }
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2024 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://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.
*/

package eu.europa.ec.eudi.rqes.core

import eu.europa.ec.eudi.rqes.AuthorizationCode
import eu.europa.ec.eudi.rqes.CSCClient
import eu.europa.ec.eudi.rqes.CredentialAuthorizationRequestPrepared
import eu.europa.ec.eudi.rqes.CredentialAuthorized
import eu.europa.ec.eudi.rqes.DocumentDigestList
import eu.europa.ec.eudi.rqes.DocumentToSign
import eu.europa.ec.eudi.rqes.HashAlgorithmOID
import eu.europa.ec.eudi.rqes.ServiceAccessAuthorized
import eu.europa.ec.eudi.rqes.Signature
import eu.europa.ec.eudi.rqes.SignaturesList
import eu.europa.ec.eudi.rqes.SigningAlgorithmOID
import eu.europa.ec.eudi.rqes.core.RQESServiceImpl.AuthorizedImpl
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import io.mockk.unmockkAll
import kotlinx.coroutines.test.runTest
import java.io.InputStream
import java.time.Instant
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test

class ExtensionsTest {
val mockClient = mockk<CSCClient>(relaxed = true)
val serverState = "server-state"
lateinit var authorizedService: AuthorizedImpl
val serviceAccessAuthorized: ServiceAccessAuthorized = mockk(relaxed = true)

@BeforeTest
fun setUp() {
authorizedService = AuthorizedImpl(
serverState = serverState,
client = mockClient,
serviceAccessAuthorized = serviceAccessAuthorized,
hashAlgorithm = HashAlgorithmOID.SHA_256,
signingAlgorithm = SigningAlgorithmOID.ECDSA_SHA256,
)
}

@AfterTest
fun tearDown() {
unmockkAll()
}

@Test
fun `test Authorized signDocuments extension`() = runTest {
val authorizationCode = AuthorizationCode(code = "let me in")
authorizedService.documentsToSign = listOf<DocumentToSign>(mockk())
authorizedService.documentDigestList = mockk<DocumentDigestList> {
every { hashAlgorithmOID } returns HashAlgorithmOID.SHA_256
every { hashCalculationTime } returns Instant.now()
}
val signatureList = mockk<SignaturesList> {
every { signatures } returns listOf<Signature>(mockk())
}
val signedDocumentsInputStreams = listOf<InputStream>(mockk())
val credentialAuthorized = mockk<CredentialAuthorized.SCAL2>() {
every { credentialCertificate } returns mockk()
coEvery {
with(mockClient) {
signHash(authorizedService.signingAlgorithm)
}
} returns Result.success(signatureList)
}

authorizedService.credAuthRequestPrepared =
mockk<CredentialAuthorizationRequestPrepared> {
coEvery {
with(mockClient) {
authorizeWithAuthorizationCode(
authorizationCode,
authorizedService.serverState
)
}
} returns Result.success(credentialAuthorized)

}

coEvery {
with(mockClient) {
getSignedDocuments(
documents = authorizedService.documentsToSign,
signatures = signatureList.signatures,
credentialCertificate = credentialAuthorized.credentialCertificate,
// hashAlgorithmOID = documentDigestList.hashAlgorithmOID,
hashAlgorithmOID = any(), // TODO: Fix this
signatureTimestamp = authorizedService.documentDigestList.hashCalculationTime
)
}
} returns signedDocumentsInputStreams

val result = authorizedService.signDocuments(authorizationCode)
assert(result.isSuccess)
}
}

0 comments on commit 28aa266

Please sign in to comment.