diff --git a/modules/openapi/build.gradle.kts b/modules/openapi/build.gradle.kts index ce5f5fef..7d913327 100644 --- a/modules/openapi/build.gradle.kts +++ b/modules/openapi/build.gradle.kts @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile plugins { kotlin("multiplatform") version "2.0.0" + kotlin("plugin.serialization") version "2.0.0" id("org.openapi.generator") version "7.7.0" id("maven-publish") } @@ -23,11 +24,26 @@ repositories { kotlin { tasks { + // Temporary fix for this issue: https://github.com/OpenAPITools/openapi-generator/issues/17658 + register("fixOpenApiGeneratorIssue") { + from( + "$projectDir/build/generated/src/commonMain/kotlin/com/sphereon/oid/fed/openapi" + ) + into( + "$projectDir/build/copy/src/commonMain/kotlin/com/sphereon/oid/fed/openapi" + ) + filter { line: String -> + line.replace( + "kotlin.collections.Map", + "kotlinx.serialization.json.JsonObject") + } + } + withType { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } named("sourcesJar") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } } jvm { @@ -58,19 +74,23 @@ kotlin { } } - named("compileKotlinJvm") { + named("fixOpenApiGeneratorIssue") { dependsOn("openApiGenerate") + } + + named("compileKotlinJvm") { + dependsOn("fixOpenApiGeneratorIssue") compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } } named("jvmSourcesJar") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } named("jvmJar") { - dependsOn("compileKotlinJvm") + dependsOn("fixOpenApiGeneratorIssue") archiveBaseName.set("openapi") duplicatesStrategy = DuplicatesStrategy.EXCLUDE from(configurations.kotlinCompilerClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) @@ -82,10 +102,10 @@ kotlin { js { tasks { named("compileKotlinJs") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } named("jsSourcesJar") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } } nodejs() @@ -94,37 +114,37 @@ kotlin { iosX64 { tasks { named("compileKotlinIosX64") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } named("iosX64SourcesJar") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } } } iosArm64 { tasks { named("compileKotlinIosArm64") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } named("iosArm64SourcesJar") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } } } iosSimulatorArm64 { tasks { named("compileKotlinIosSimulatorArm64") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } named("iosSimulatorArm64SourcesJar") { - dependsOn("openApiGenerate") + dependsOn("fixOpenApiGeneratorIssue") } } } sourceSets { val commonMain by getting { - kotlin.srcDir("build/generated/src/commonMain/kotlin") + kotlin.srcDir("build/copy/src/commonMain/kotlin") dependencies { implementation("io.ktor:ktor-client-core:$ktorVersion") implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") diff --git a/modules/openapi/gradle.properties b/modules/openapi/gradle.properties index 33cf166a..08d60d78 100644 --- a/modules/openapi/gradle.properties +++ b/modules/openapi/gradle.properties @@ -1,2 +1,2 @@ kotlin.code.style=official -profiles=models-only +#profiles=models-only diff --git a/modules/openid-federation-common/build.gradle.kts b/modules/openid-federation-common/build.gradle.kts index 028874bd..3e9d899b 100644 --- a/modules/openid-federation-common/build.gradle.kts +++ b/modules/openid-federation-common/build.gradle.kts @@ -40,9 +40,9 @@ kotlin { } } - iosX64() - iosArm64() - iosSimulatorArm64() +// iosX64() +// iosArm64() +// iosSimulatorArm64() jvm() @@ -50,8 +50,11 @@ kotlin { val commonMain by getting { dependencies { implementation("com.sphereon.oid.fed:openapi:0.1.0-SNAPSHOT") - runtimeOnly("io.ktor:ktor-client-core:$ktorVersion") - runtimeOnly("io.ktor:ktor-client-logging:$ktorVersion") + implementation("io.ktor:ktor-client-core:$ktorVersion") + implementation("io.ktor:ktor-client-logging:$ktorVersion") + implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") + implementation("io.ktor:ktor-client-auth:$ktorVersion") + implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.0") implementation(libs.kermit.logging) @@ -61,6 +64,7 @@ kotlin { dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) + implementation("io.ktor:ktor-client-mock:$ktorVersion") } } val jvmMain by getting { @@ -87,40 +91,40 @@ kotlin { } } - val iosMain by creating { - dependsOn(commonMain) - dependencies { - - } - } - val iosX64Main by getting { - //dependsOn(iosMain) - dependencies { - implementation("io.ktor:ktor-client-core-iosx64:$ktorVersion") - implementation("io.ktor:ktor-client-cio-iosx64:$ktorVersion") - } - } - val iosArm64Main by getting { - dependsOn(iosX64Main) - dependencies { - implementation("io.ktor:ktor-client-core-iosarm64:$ktorVersion") - implementation("io.ktor:ktor-client-cio-iosarm64:$ktorVersion") - } - } - val iosSimulatorArm64Main by getting { - dependsOn(iosX64Main) - dependencies { - implementation("io.ktor:ktor-client-core-iossimulatorarm64:$ktorVersion") - implementation("io.ktor:ktor-client-cio-iossimulatorarm64:$ktorVersion") - } - } - - val iosTest by creating { - dependsOn(commonTest) - dependencies { - implementation(kotlin("test")) - } - } +// val iosMain by creating { +// dependsOn(commonMain) +// dependencies { +// implementation("io.ktor:ktor-client-core-ios:$ktorVersion") +// } +// } +// val iosX64Main by getting { +// dependsOn(iosMain) +// dependencies { +// implementation("io.ktor:ktor-client-core-iosx64:$ktorVersion") +// implementation("io.ktor:ktor-client-cio-iosx64:$ktorVersion") +// } +// } +// val iosArm64Main by getting { +// dependsOn(iosMain) +// dependencies { +// implementation("io.ktor:ktor-client-core-iosarm64:$ktorVersion") +// implementation("io.ktor:ktor-client-cio-iosarm64:$ktorVersion") +// } +// } +// val iosSimulatorArm64Main by getting { +// dependsOn(iosMain) +// dependencies { +// implementation("io.ktor:ktor-client-core-iossimulatorarm64:$ktorVersion") +// implementation("io.ktor:ktor-client-cio-iossimulatorarm64:$ktorVersion") +// } +// } + +// val iosTest by creating { +// dependsOn(commonTest) +// dependencies { +// implementation(kotlin("test")) +// } +// } val jsMain by getting { dependencies { diff --git a/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClient.kt b/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClient.kt index c9faeba2..6fa78a6b 100644 --- a/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClient.kt +++ b/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClient.kt @@ -1,17 +1,51 @@ -package nl.zoe.httpclient +package com.sphereon.oid.fed.common.httpclient import com.sphereon.oid.fed.openapi.models.EntityStatement import io.ktor.client.* import io.ktor.client.call.* +import io.ktor.client.engine.* +import io.ktor.client.plugins.auth.* +import io.ktor.client.plugins.auth.providers.* +import io.ktor.client.plugins.cache.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.plugins.logging.* import io.ktor.client.request.* import io.ktor.client.request.forms.* import io.ktor.http.* import io.ktor.http.HttpMethod.Companion.Get import io.ktor.http.HttpMethod.Companion.Post +import io.ktor.serialization.kotlinx.json.* +import io.ktor.utils.io.core.* class OidFederationClient( - private val client: HttpClient + engine: HttpClientEngine, + isRequestAuthenticated: Boolean = false, + isRequestCached: Boolean = false ) { + private val client: HttpClient = HttpClient(engine) { + install(HttpCache) + install(ContentNegotiation) { + json() + } + install(Logging) { + logger = Logger.DEFAULT + level = LogLevel.INFO + } + if (isRequestAuthenticated) { + install(Auth) { + bearer { + loadTokens { + //TODO add correct implementation later + BearerTokens("accessToken", "refreshToken") + } + } + } + } + if (isRequestCached) { + install(HttpCache) + } + } + suspend fun fetchEntityStatement(url: String, httpMethod: HttpMethod = Get, parameters: Parameters = Parameters.Empty): EntityStatement { return when (httpMethod) { Get -> getEntityStatement(url) @@ -31,4 +65,4 @@ class OidFederationClient( }.body() } } -} \ No newline at end of file +} diff --git a/modules/openid-federation-common/src/jvmTest/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClientTest.kt b/modules/openid-federation-common/src/jvmTest/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClientTest.kt new file mode 100644 index 00000000..19925cd4 --- /dev/null +++ b/modules/openid-federation-common/src/jvmTest/kotlin/com/sphereon/oid/fed/common/httpclient/OidFederationClientTest.kt @@ -0,0 +1,46 @@ +package com.sphereon.oid.fed.common.httpclient + +import com.sphereon.oid.fed.openapi.models.EntityStatement +import com.sphereon.oid.fed.openapi.models.FederationEntityMetadata +import com.sphereon.oid.fed.openapi.models.Metadata +import io.ktor.client.engine.mock.* +import io.ktor.http.* +import io.ktor.utils.io.* +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import kotlin.test.Test + +class OidFederationClientTest { + + private val entityStatement = EntityStatement( + iss = "test_iss", + sub = "test_sub", + metadata = Metadata( + federationEntity = FederationEntityMetadata( + federationListEndpoint = "http://www.example.com/list", + federationResolveEndpoint = "http://www.example.com/resolve", + organizationName = "test organization", + homepageUri = "http://www.example.com", + federationFetchEndpoint = "http://www.example.com/fetch", + ) + ) + ) + + private val mockEngine = MockEngine { + respond( + content = ByteReadChannel(Json.encodeToString(entityStatement)), + status = HttpStatusCode.OK, + headers = headersOf(HttpHeaders.ContentType, "application/json") + ) + } + + @Test + fun testGetEntityStatement() { + runBlocking { + val client = OidFederationClient(mockEngine) + val response = client.fetchEntityStatement("test_iss", HttpMethod.Get) + assert(response == entityStatement) + } + } +} \ No newline at end of file