Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(credentials) #54: validate required endpoints #58

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ import com.izivia.ocpi.toolkit.transport.TransportClientBuilder
* @property clientCredentialsRoleRepository client's repository to retrieve its role
* @property serverVersionsEndpointUrl the versions endpoint url of the server (for the client to retrieve endpoints)
* @property transportClientBuilder used to build a transport (will be used to create CredentialClient to make calls)
* @property requiredEndpoints the endpoints this client expects from the other part to provide
*/
class CredentialsClientService(
private val clientVersionsEndpointUrl: String,
private val clientPartnerRepository: PartnerRepository,
private val clientVersionsRepository: VersionsRepository,
private val clientCredentialsRoleRepository: CredentialsRoleRepository,
private val serverVersionsEndpointUrl: String,
private val transportClientBuilder: TransportClientBuilder
private val transportClientBuilder: TransportClientBuilder,
private val requiredEndpoints: RequiredEndpoints?
) {
suspend fun get(): Credentials = clientPartnerRepository
.getCredentialsClientToken(partnerUrl = serverVersionsEndpointUrl)
Expand Down Expand Up @@ -226,6 +228,8 @@ class CredentialsClientService(
it.data ?: throw OcpiResponseException(it.status_code, it.status_message ?: "unknown")
}

checkRequiredEndpoints(requiredEndpoints, versionDetails.endpoints)

// Store version & endpoint
return clientPartnerRepository.saveEndpoints(
partnerUrl = serverVersionsEndpointUrl,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.izivia.ocpi.toolkit.modules.credentials.services

import com.izivia.ocpi.toolkit.common.OcpiServerNoMatchingEndpointsException
import com.izivia.ocpi.toolkit.modules.versions.domain.Endpoint
import com.izivia.ocpi.toolkit.modules.versions.domain.InterfaceRole
import com.izivia.ocpi.toolkit.modules.versions.domain.ModuleID

data class RequiredEndpoints(
val receiver: List<ModuleID> = listOf(),
val sender: List<ModuleID> = listOf()
)

fun checkRequiredEndpoints(
requiredEndpoints: RequiredEndpoints?,
actualEndpoints: List<Endpoint>
) {
if (requiredEndpoints == null) {
return
}

actualEndpoints
.find { it.identifier == ModuleID.credentials }
?: throw OcpiServerNoMatchingEndpointsException("${ModuleID.credentials} endpoint missing")

checkRequiredRoleEndpoints(actualEndpoints, requiredEndpoints.receiver, InterfaceRole.RECEIVER)
checkRequiredRoleEndpoints(actualEndpoints, requiredEndpoints.sender, InterfaceRole.SENDER)
}

private fun checkRequiredRoleEndpoints(
endpoints: List<Endpoint>,
requiredEndpoints: List<ModuleID>,
role: InterfaceRole
) {
for (requiredEndpoint in requiredEndpoints) {
endpoints
.find {
requiredEndpoint == ModuleID.credentials ||
(it.role == role && it.identifier == requiredEndpoint)
}
?: throw OcpiServerNoMatchingEndpointsException("${requiredEndpoint.name} as ${role.name} endpoint missing")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import com.izivia.ocpi.toolkit.modules.credentials.CredentialsInterface
import com.izivia.ocpi.toolkit.modules.credentials.domain.Credentials
import com.izivia.ocpi.toolkit.modules.credentials.repositories.CredentialsRoleRepository
import com.izivia.ocpi.toolkit.modules.credentials.repositories.PartnerRepository
import com.izivia.ocpi.toolkit.modules.versions.domain.Version
import com.izivia.ocpi.toolkit.modules.versions.domain.VersionDetails
import com.izivia.ocpi.toolkit.modules.versions.domain.VersionNumber
import com.izivia.ocpi.toolkit.modules.versions.domain.*
import com.izivia.ocpi.toolkit.transport.TransportClientBuilder
import com.izivia.ocpi.toolkit.transport.domain.HttpMethod
import com.izivia.ocpi.toolkit.transport.domain.HttpRequest
Expand All @@ -17,7 +15,8 @@ class CredentialsServerService(
private val partnerRepository: PartnerRepository,
private val credentialsRoleRepository: CredentialsRoleRepository,
private val transportClientBuilder: TransportClientBuilder,
private val serverVersionsUrlProvider: suspend () -> String
private val serverVersionsUrlProvider: suspend () -> String,
private val requiredEndpoints: RequiredEndpoints?
) : CredentialsInterface {

override suspend fun get(
Expand Down Expand Up @@ -202,6 +201,8 @@ class CredentialsServerService(
)
}

checkRequiredEndpoints(requiredEndpoints, versionDetail.endpoints)

partnerRepository.saveEndpoints(partnerUrl = credentials.url, endpoints = versionDetail.endpoints)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import com.izivia.ocpi.toolkit.modules.credentials.domain.CredentialRole
import com.izivia.ocpi.toolkit.modules.credentials.domain.Role
import com.izivia.ocpi.toolkit.modules.credentials.repositories.CredentialsRoleRepository
import com.izivia.ocpi.toolkit.modules.credentials.services.CredentialsServerService
import com.izivia.ocpi.toolkit.modules.credentials.services.RequiredEndpoints
import com.izivia.ocpi.toolkit.modules.locations.domain.BusinessDetails
import com.izivia.ocpi.toolkit.modules.versions.VersionDetailsServer
import com.izivia.ocpi.toolkit.modules.versions.VersionsServer
import com.izivia.ocpi.toolkit.modules.versions.domain.ModuleID
import com.izivia.ocpi.toolkit.modules.versions.services.VersionDetailsService
import com.izivia.ocpi.toolkit.modules.versions.services.VersionsService
import com.izivia.ocpi.toolkit.samples.common.*
Expand All @@ -30,6 +32,8 @@ fun main() {
secureFilter = receiverPlatformRepository::checkToken
)

val requiredOtherPartEndpoints = RequiredEndpoints(receiver = listOf(ModuleID.credentials))

runBlocking {
CredentialsServer(
service = CredentialsServerService(
Expand All @@ -45,7 +49,8 @@ fun main() {
)
},
transportClientBuilder = Http4kTransportClientBuilder(),
serverVersionsUrlProvider = { receiverVersionsUrl }
serverVersionsUrlProvider = { receiverVersionsUrl },
requiredEndpoints = requiredOtherPartEndpoints
)
).registerOn(receiverServer)
VersionsServer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import com.izivia.ocpi.toolkit.modules.credentials.domain.CredentialRole
import com.izivia.ocpi.toolkit.modules.credentials.domain.Role
import com.izivia.ocpi.toolkit.modules.credentials.repositories.CredentialsRoleRepository
import com.izivia.ocpi.toolkit.modules.credentials.services.CredentialsClientService
import com.izivia.ocpi.toolkit.modules.credentials.services.RequiredEndpoints
import com.izivia.ocpi.toolkit.modules.locations.domain.BusinessDetails
import com.izivia.ocpi.toolkit.modules.versions.VersionDetailsServer
import com.izivia.ocpi.toolkit.modules.versions.VersionsServer
import com.izivia.ocpi.toolkit.modules.versions.domain.ModuleID
import com.izivia.ocpi.toolkit.modules.versions.services.VersionDetailsService
import com.izivia.ocpi.toolkit.modules.versions.services.VersionsService
import com.izivia.ocpi.toolkit.samples.common.*
Expand Down Expand Up @@ -61,7 +63,8 @@ fun main() {
)
},
serverVersionsEndpointUrl = receiverVersionsUrl,
transportClientBuilder = Http4kTransportClientBuilder()
transportClientBuilder = Http4kTransportClientBuilder(),
requiredEndpoints = RequiredEndpoints(receiver = listOf(ModuleID.credentials))
)

runBlocking {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import com.izivia.ocpi.toolkit.modules.credentials.domain.Role
import com.izivia.ocpi.toolkit.modules.credentials.repositories.CredentialsRoleRepository
import com.izivia.ocpi.toolkit.modules.credentials.services.CredentialsClientService
import com.izivia.ocpi.toolkit.modules.credentials.services.CredentialsServerService
import com.izivia.ocpi.toolkit.modules.credentials.services.RequiredEndpoints
import com.izivia.ocpi.toolkit.modules.locations.domain.BusinessDetails
import com.izivia.ocpi.toolkit.modules.versions.VersionDetailsServer
import com.izivia.ocpi.toolkit.modules.versions.VersionsClient
import com.izivia.ocpi.toolkit.modules.versions.VersionsServer
import com.izivia.ocpi.toolkit.modules.versions.domain.ModuleID
import com.izivia.ocpi.toolkit.modules.versions.services.VersionDetailsService
import com.izivia.ocpi.toolkit.modules.versions.services.VersionsService
import com.izivia.ocpi.toolkit.samples.common.*
Expand All @@ -23,6 +25,7 @@ import com.mongodb.client.MongoDatabase
import kotlinx.coroutines.runBlocking
import org.eclipse.jetty.client.HttpResponseException
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.litote.kmongo.eq
import org.litote.kmongo.getCollection
import strikt.api.expectCatching
Expand All @@ -42,7 +45,7 @@ class CredentialsIntegrationTests : BaseServerIntegrationTest() {

private var database: MongoDatabase? = null

private fun setupReceiver(): ServerSetupResult {
private fun setupReceiver(requiredEndpoints: RequiredEndpoints? = null): ServerSetupResult {
if (database == null) database = buildDBClient().getDatabase("ocpi-2-2-1-tests")
val receiverPartnerCollection = database!!
.getCollection<Partner>("receiver-server-${UUID.randomUUID()}")
Expand Down Expand Up @@ -72,7 +75,8 @@ class CredentialsIntegrationTests : BaseServerIntegrationTest() {
)
},
transportClientBuilder = Http4kTransportClientBuilder(),
serverVersionsUrlProvider = { receiverServerVersionsUrl }
serverVersionsUrlProvider = { receiverServerVersionsUrl },
requiredEndpoints = requiredEndpoints
)
).registerOn(receiverServer)
VersionsServer(
Expand Down Expand Up @@ -129,7 +133,8 @@ class CredentialsIntegrationTests : BaseServerIntegrationTest() {

private fun setupCredentialsSenderClient(
senderServerSetupResult: ServerSetupResult,
receiverServerSetupResult: ServerSetupResult
receiverServerSetupResult: ServerSetupResult,
requiredEndpoints: RequiredEndpoints? = null
): CredentialsClientService {
// Setup sender (client)
return CredentialsClientService(
Expand All @@ -147,7 +152,8 @@ class CredentialsIntegrationTests : BaseServerIntegrationTest() {
)
},
serverVersionsEndpointUrl = receiverServerSetupResult.versionsEndpoint,
transportClientBuilder = Http4kTransportClientBuilder()
transportClientBuilder = Http4kTransportClientBuilder(),
requiredEndpoints = requiredEndpoints
)
}

Expand Down Expand Up @@ -248,9 +254,50 @@ class CredentialsIntegrationTests : BaseServerIntegrationTest() {
}
}

@Test
fun `should not properly run registration process because required endpoints are missing`() {
val receiverServer = setupReceiver(
RequiredEndpoints(
receiver = listOf(ModuleID.credentials, ModuleID.locations),
sender = listOf(ModuleID.chargingprofiles)
)
)
val senderServer = setupSender()

val credentialsClientService = setupCredentialsSenderClient(
senderServerSetupResult = senderServer,
receiverServerSetupResult = receiverServer
)

// Store token A on the receiver side, that will be used by the sender to begin registration and store it as
// well in the client so that it knows what token to send
val tokenA = UUID.randomUUID().toString()
receiverServer.partnerCollection.insertOne(Partner(url = senderServer.versionsEndpoint, tokenA = tokenA))
senderServer.partnerCollection.insertOne(Partner(url = receiverServer.versionsEndpoint, tokenA = tokenA))

// Start the servers
receiverServer.transport.start()
senderServer.transport.start()

expectThat(
assertThrows<OcpiResponseException> {
runBlocking {
credentialsClientService.register()
}
}
) {
get { statusCode }
.isEqualTo(OcpiStatus.SERVER_NO_MATCHING_ENDPOINTS.code)
}
}

@Test
fun `should properly run registration process then correct get credentials from receiver`() {
val receiverServer = setupReceiver()
val receiverServer = setupReceiver(
RequiredEndpoints(
receiver = listOf(ModuleID.credentials, ModuleID.locations)
)
)
val senderServer = setupSender()

val credentialsClientService = setupCredentialsSenderClient(
Expand Down