diff --git a/build.gradle.kts b/build.gradle.kts index 59577343..54780dc5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -58,6 +58,7 @@ dependencies { implementation("io.ktor:ktor-client-core:$ktor_version") implementation("io.ktor:ktor-client-cio:$ktor_version") implementation("io.ktor:ktor-client-content-negotiation:$ktor_version") + testImplementation("io.ktor:ktor-client-mock:$ktor_version") implementation("tech.barbero.http-messages-signing:http-messages-signing-core:1.0.0") diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt index ec3159a4..c1076899 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt @@ -122,7 +122,8 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo } override fun addHeader(name: String?, value: String?) { - name?.let { request.header(it, "\"${value?.trim(',')}\"") } + val split = value?.split("=").orEmpty() + name?.let { request.header(it, split.get(0)+"=\""+split.get(1).trim('"')+"\"") } } override fun method(): String { diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt new file mode 100644 index 00000000..8d303ef8 --- /dev/null +++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt @@ -0,0 +1,122 @@ +package dev.usbharu.hideout.plugins + +import dev.usbharu.hideout.ap.JsonLd +import dev.usbharu.hideout.domain.model.User +import dev.usbharu.hideout.domain.model.UserAuthentication +import dev.usbharu.hideout.domain.model.UserAuthenticationEntity +import dev.usbharu.hideout.domain.model.UserEntity +import dev.usbharu.hideout.repository.IUserAuthRepository +import dev.usbharu.hideout.repository.IUserRepository +import dev.usbharu.hideout.service.UserAuthService +import io.ktor.client.* +import io.ktor.client.engine.mock.* +import io.ktor.client.plugins.logging.* +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Test +import java.security.KeyPairGenerator +import java.security.interfaces.RSAPrivateKey +import java.security.interfaces.RSAPublicKey +import java.util.* + +class ActivityPubKtTest { + @Test + fun HttpSignTest(): Unit = runBlocking { + + val ktorKeyMap = KtorKeyMap(UserAuthService(object : IUserRepository { + override suspend fun create(user: User): UserEntity { + TODO("Not yet implemented") + } + + override suspend fun findById(id: Long): UserEntity? { + TODO("Not yet implemented") + } + + override suspend fun findByName(name: String): UserEntity? { + return UserEntity(1, "test", "localhost", "test", "") + } + + override suspend fun update(userEntity: UserEntity) { + TODO("Not yet implemented") + } + + override suspend fun delete(id: Long) { + TODO("Not yet implemented") + } + + override suspend fun findAll(): List { + TODO("Not yet implemented") + } + + override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List { + TODO("Not yet implemented") + } + + override suspend fun createFollower(id: Long, follower: Long) { + TODO("Not yet implemented") + } + + override suspend fun deleteFollower(id: Long, follower: Long) { + TODO("Not yet implemented") + } + + override suspend fun findFollowersById(id: Long): List { + TODO("Not yet implemented") + } + + }, object : IUserAuthRepository { + override suspend fun create(userAuthentication: UserAuthentication): UserAuthenticationEntity { + TODO("Not yet implemented") + } + + override suspend fun findById(id: Long): UserAuthenticationEntity? { + TODO("Not yet implemented") + } + + override suspend fun update(userAuthenticationEntity: UserAuthenticationEntity) { + TODO("Not yet implemented") + } + + override suspend fun delete(id: Long) { + TODO("Not yet implemented") + } + + override suspend fun findByUserId(id: Long): UserAuthenticationEntity? { + val keyPairGenerator = KeyPairGenerator.getInstance("RSA") + keyPairGenerator.initialize(1024) + val generateKeyPair = keyPairGenerator.generateKeyPair() + return UserAuthenticationEntity( + 1, 1, "test", (generateKeyPair.public as RSAPublicKey).toPem(), + (generateKeyPair.private as RSAPrivateKey).toPem() + ) + } + })) + + val httpClient = HttpClient(MockEngine { httpRequestData -> + respondOk() + }) { + install(httpSignaturePlugin) { + keyMap = ktorKeyMap + } + install(Logging) { + logger = Logger.DEFAULT + level = LogLevel.ALL + } + } + + httpClient.postAp("https://localhost", "test", JsonLd(emptyList())) + + + } + + fun RSAPublicKey.toPem(): String { + return "-----BEGIN RSA PUBLIC KEY-----" + + Base64.getEncoder().encodeToString(encoded) + + "-----END RSA PUBLIC KEY-----" + } + + fun RSAPrivateKey.toPem(): String { + return "-----BEGIN RSA PRIVATE KEY-----" + + Base64.getEncoder().encodeToString(encoded) + + "-----END RSA PRIVATE KEY-----" + } +}