mirror of https://github.com/usbharu/Hideout.git
feat: APRequestServiceに切り替え
This commit is contained in:
parent
1fba688a74
commit
d6ecad976b
|
@ -1,7 +1,6 @@
|
||||||
package dev.usbharu.hideout.config
|
package dev.usbharu.hideout.config
|
||||||
|
|
||||||
import dev.usbharu.hideout.plugins.KtorKeyMap
|
import dev.usbharu.hideout.plugins.KtorKeyMap
|
||||||
import dev.usbharu.hideout.plugins.httpSignaturePlugin
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
|
@ -16,9 +15,6 @@ import tech.barbero.http.message.signing.KeyMap
|
||||||
class HttpClientConfig {
|
class HttpClientConfig {
|
||||||
@Bean
|
@Bean
|
||||||
fun httpClient(keyMap: KeyMap): HttpClient = HttpClient(CIO).config {
|
fun httpClient(keyMap: KeyMap): HttpClient = HttpClient(CIO).config {
|
||||||
install(httpSignaturePlugin) {
|
|
||||||
this.keyMap = keyMap
|
|
||||||
}
|
|
||||||
install(Logging) {
|
install(Logging) {
|
||||||
logger = Logger.DEFAULT
|
logger = Logger.DEFAULT
|
||||||
level = LogLevel.INFO
|
level = LogLevel.INFO
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
package dev.usbharu.hideout.plugins
|
package dev.usbharu.hideout.plugins
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import dev.usbharu.hideout.config.ApplicationConfig
|
import dev.usbharu.hideout.config.ApplicationConfig
|
||||||
import dev.usbharu.hideout.domain.model.ap.JsonLd
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.UserAuthServiceImpl
|
import dev.usbharu.hideout.service.user.UserAuthServiceImpl
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
|
||||||
import io.ktor.client.*
|
|
||||||
import io.ktor.client.plugins.api.*
|
import io.ktor.client.plugins.api.*
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.client.statement.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import tech.barbero.http.message.signing.HttpMessage
|
import tech.barbero.http.message.signing.HttpMessage
|
||||||
|
@ -27,31 +22,6 @@ import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.crypto.SecretKey
|
import javax.crypto.SecretKey
|
||||||
|
|
||||||
suspend fun HttpClient.postAp(
|
|
||||||
urlString: String,
|
|
||||||
username: String,
|
|
||||||
jsonLd: JsonLd,
|
|
||||||
objectMapper: ObjectMapper
|
|
||||||
): HttpResponse {
|
|
||||||
jsonLd.context += "https://www.w3.org/ns/activitystreams"
|
|
||||||
return this.post(urlString) {
|
|
||||||
header("Accept", ContentType.Application.Activity)
|
|
||||||
header("Content-Type", ContentType.Application.Activity)
|
|
||||||
header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) digest date\"")
|
|
||||||
val text = objectMapper.writeValueAsString(jsonLd)
|
|
||||||
setBody(text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun HttpClient.getAp(urlString: String, username: String?): HttpResponse {
|
|
||||||
return this.get(urlString) {
|
|
||||||
header("Accept", ContentType.Application.Activity)
|
|
||||||
username?.let {
|
|
||||||
header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HttpSignaturePluginConfig {
|
class HttpSignaturePluginConfig {
|
||||||
lateinit var keyMap: KeyMap
|
lateinit var keyMap: KeyMap
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import dev.usbharu.hideout.domain.model.job.DeliverPostJob
|
||||||
import dev.usbharu.hideout.exception.FailedToGetResourcesException
|
import dev.usbharu.hideout.exception.FailedToGetResourcesException
|
||||||
import dev.usbharu.hideout.exception.ap.FailedToGetActivityPubResourceException
|
import dev.usbharu.hideout.exception.ap.FailedToGetActivityPubResourceException
|
||||||
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.plugins.postAp
|
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.MediaQueryService
|
import dev.usbharu.hideout.query.MediaQueryService
|
||||||
import dev.usbharu.hideout.query.PostQueryService
|
import dev.usbharu.hideout.query.PostQueryService
|
||||||
|
@ -20,6 +19,7 @@ import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.repository.PostRepository
|
import dev.usbharu.hideout.repository.PostRepository
|
||||||
import dev.usbharu.hideout.service.ap.resource.APResourceResolveService
|
import dev.usbharu.hideout.service.ap.resource.APResourceResolveService
|
||||||
import dev.usbharu.hideout.service.ap.resource.resolve
|
import dev.usbharu.hideout.service.ap.resource.resolve
|
||||||
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import dev.usbharu.hideout.service.post.PostCreateInterceptor
|
import dev.usbharu.hideout.service.post.PostCreateInterceptor
|
||||||
import dev.usbharu.hideout.service.post.PostService
|
import dev.usbharu.hideout.service.post.PostService
|
||||||
|
@ -69,7 +69,9 @@ class APNoteServiceImpl(
|
||||||
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
||||||
private val applicationConfig: ApplicationConfig,
|
private val applicationConfig: ApplicationConfig,
|
||||||
private val postService: PostService,
|
private val postService: PostService,
|
||||||
private val apResourceResolveService: APResourceResolveService
|
private val apResourceResolveService: APResourceResolveService,
|
||||||
|
private val apRequestService: APRequestService,
|
||||||
|
private val transaction: Transaction
|
||||||
|
|
||||||
) : APNoteService, PostCreateInterceptor {
|
) : APNoteService, PostCreateInterceptor {
|
||||||
|
|
||||||
|
@ -121,17 +123,20 @@ class APNoteServiceImpl(
|
||||||
)
|
)
|
||||||
val inbox = props[DeliverPostJob.inbox]
|
val inbox = props[DeliverPostJob.inbox]
|
||||||
logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox)
|
logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox)
|
||||||
httpClient.postAp(
|
|
||||||
urlString = inbox,
|
transaction.transaction {
|
||||||
username = "$actor#pubkey",
|
val signer = userQueryService.findByUrl(actor)
|
||||||
jsonLd = Create(
|
apRequestService.apPost(
|
||||||
name = "Create Note",
|
inbox, Create(
|
||||||
`object` = note,
|
name = "Create Note",
|
||||||
actor = note.attributedTo,
|
`object` = note,
|
||||||
id = "${applicationConfig.url}/create/note/${postEntity.id}"
|
actor = note.attributedTo,
|
||||||
),
|
id = "${applicationConfig.url}/create/note/${postEntity.id}"
|
||||||
objectMapper
|
), signer
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchNote(url: String, targetActor: String?): Note {
|
override suspend fun fetchNote(url: String, targetActor: String?): Note {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import dev.usbharu.hideout.domain.model.ap.Undo
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
||||||
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
|
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
|
||||||
import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob
|
import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob
|
||||||
import dev.usbharu.hideout.plugins.postAp
|
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.PostQueryService
|
import dev.usbharu.hideout.query.PostQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
|
@ -34,8 +33,8 @@ class APReactionServiceImpl(
|
||||||
private val followerQueryService: FollowerQueryService,
|
private val followerQueryService: FollowerQueryService,
|
||||||
private val postQueryService: PostQueryService,
|
private val postQueryService: PostQueryService,
|
||||||
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
||||||
private val applicationConfig: ApplicationConfig
|
private val applicationConfig: ApplicationConfig,
|
||||||
|
private val apRequestService: APRequestService
|
||||||
) : APReactionService {
|
) : APReactionService {
|
||||||
override suspend fun reaction(like: Reaction) {
|
override suspend fun reaction(like: Reaction) {
|
||||||
val followers = followerQueryService.findFollowersById(like.userId)
|
val followers = followerQueryService.findFollowersById(like.userId)
|
||||||
|
@ -74,17 +73,17 @@ class APReactionServiceImpl(
|
||||||
val postUrl = props[DeliverReactionJob.postUrl]
|
val postUrl = props[DeliverReactionJob.postUrl]
|
||||||
val id = props[DeliverReactionJob.id]
|
val id = props[DeliverReactionJob.id]
|
||||||
val content = props[DeliverReactionJob.reaction]
|
val content = props[DeliverReactionJob.reaction]
|
||||||
httpClient.postAp(
|
|
||||||
urlString = inbox,
|
val signer = userQueryService.findByUrl(actor)
|
||||||
username = "$actor#pubkey",
|
|
||||||
jsonLd = Like(
|
apRequestService.apPost(
|
||||||
|
inbox, Like(
|
||||||
name = "Like",
|
name = "Like",
|
||||||
actor = actor,
|
actor = actor,
|
||||||
`object` = postUrl,
|
`object` = postUrl,
|
||||||
id = "${applicationConfig.url}/like/note/$id",
|
id = "${applicationConfig.url}/like/note/$id",
|
||||||
content = content
|
content = content
|
||||||
),
|
), signer
|
||||||
objectMapper
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,17 +91,17 @@ class APReactionServiceImpl(
|
||||||
val inbox = props[DeliverRemoveReactionJob.inbox]
|
val inbox = props[DeliverRemoveReactionJob.inbox]
|
||||||
val actor = props[DeliverRemoveReactionJob.actor]
|
val actor = props[DeliverRemoveReactionJob.actor]
|
||||||
val like = objectMapper.readValue<Like>(props[DeliverRemoveReactionJob.like])
|
val like = objectMapper.readValue<Like>(props[DeliverRemoveReactionJob.like])
|
||||||
httpClient.postAp(
|
|
||||||
urlString = inbox,
|
val signer = userQueryService.findByUrl(actor)
|
||||||
username = "$actor#pubkey",
|
|
||||||
jsonLd = Undo(
|
apRequestService.apPost(
|
||||||
|
inbox, Undo(
|
||||||
name = "Undo Reaction",
|
name = "Undo Reaction",
|
||||||
actor = actor,
|
actor = actor,
|
||||||
`object` = like,
|
`object` = like,
|
||||||
id = "${applicationConfig.url}/undo/note/${like.id}",
|
id = "${applicationConfig.url}/undo/note/${like.id}",
|
||||||
published = Instant.now()
|
published = Instant.now()
|
||||||
),
|
), signer
|
||||||
objectMapper
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
||||||
import dev.usbharu.hideout.domain.model.ap.Accept
|
import dev.usbharu.hideout.domain.model.ap.Accept
|
||||||
import dev.usbharu.hideout.domain.model.ap.Follow
|
import dev.usbharu.hideout.domain.model.ap.Follow
|
||||||
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
|
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
|
||||||
import dev.usbharu.hideout.plugins.postAp
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
|
@ -31,7 +30,8 @@ class APReceiveFollowServiceImpl(
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val transaction: Transaction,
|
private val transaction: Transaction,
|
||||||
@Qualifier("activitypub") private val objectMapper: ObjectMapper
|
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
||||||
|
private val apRequestService: APRequestService
|
||||||
) : APReceiveFollowService {
|
) : APReceiveFollowService {
|
||||||
override suspend fun receiveFollow(follow: Follow): ActivityPubResponse {
|
override suspend fun receiveFollow(follow: Follow): ActivityPubResponse {
|
||||||
// TODO: Verify HTTP Signature
|
// TODO: Verify HTTP Signature
|
||||||
|
@ -50,15 +50,17 @@ class APReceiveFollowServiceImpl(
|
||||||
val targetActor = props[ReceiveFollowJob.targetActor]
|
val targetActor = props[ReceiveFollowJob.targetActor]
|
||||||
val person = apUserService.fetchPerson(actor, targetActor)
|
val person = apUserService.fetchPerson(actor, targetActor)
|
||||||
val follow = objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow])
|
val follow = objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow])
|
||||||
httpClient.postAp(
|
|
||||||
urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"),
|
val signer = userQueryService.findByUrl(actor)
|
||||||
username = "$targetActor#pubkey",
|
|
||||||
jsonLd = Accept(
|
val urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found")
|
||||||
|
|
||||||
|
apRequestService.apPost(
|
||||||
|
urlString, Accept(
|
||||||
name = "Follow",
|
name = "Follow",
|
||||||
`object` = follow,
|
`object` = follow,
|
||||||
actor = targetActor
|
actor = targetActor
|
||||||
),
|
), signer
|
||||||
objectMapper
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val targetEntity = userQueryService.findByUrl(targetActor)
|
val targetEntity = userQueryService.findByUrl(targetActor)
|
||||||
|
|
|
@ -11,6 +11,8 @@ interface APRequestService {
|
||||||
signer: User? = null,
|
signer: User? = null,
|
||||||
responseClass: Class<R>
|
responseClass: Class<R>
|
||||||
): R
|
): R
|
||||||
|
|
||||||
|
suspend fun <T : Object> apPost(url: String, body: T? = null, signer: User? = null): String
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun <reified R : Object> APRequestService.apGet(url: String, signer: User? = null): R =
|
suspend inline fun <reified R : Object> APRequestService.apGet(url: String, signer: User? = null): R =
|
||||||
|
|
|
@ -16,8 +16,8 @@ import org.springframework.beans.factory.annotation.Qualifier
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
|
import java.time.ZonedDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -30,7 +30,7 @@ class APRequestServiceImpl(
|
||||||
|
|
||||||
override suspend fun <R : Object> apGet(url: String, signer: User?, responseClass: Class<R>): R {
|
override suspend fun <R : Object> apGet(url: String, signer: User?, responseClass: Class<R>): R {
|
||||||
|
|
||||||
val date = dateTimeFormatter.format(LocalDateTime.now(ZoneId.of("GMT")))
|
val date = dateTimeFormatter.format(ZonedDateTime.now(ZoneId.of("GMT")))
|
||||||
val u = URL(url)
|
val u = URL(url)
|
||||||
if (signer?.privateKey == null) {
|
if (signer?.privateKey == null) {
|
||||||
val bodyAsText = httpClient.get(url) {
|
val bodyAsText = httpClient.get(url) {
|
||||||
|
@ -71,6 +71,11 @@ class APRequestServiceImpl(
|
||||||
signer: User?,
|
signer: User?,
|
||||||
responseClass: Class<R>
|
responseClass: Class<R>
|
||||||
): R {
|
): R {
|
||||||
|
val bodyAsText = apPost(url, body, signer)
|
||||||
|
return objectMapper.readValue(bodyAsText, responseClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun <T : Object> apPost(url: String, body: T?, signer: User?): String {
|
||||||
|
|
||||||
val requestBody = objectMapper.writeValueAsString(body)
|
val requestBody = objectMapper.writeValueAsString(body)
|
||||||
|
|
||||||
|
@ -78,17 +83,16 @@ class APRequestServiceImpl(
|
||||||
|
|
||||||
val digest = Base64Util.encode(sha256.digest(requestBody.toByteArray()))
|
val digest = Base64Util.encode(sha256.digest(requestBody.toByteArray()))
|
||||||
|
|
||||||
val date = dateTimeFormatter.format(LocalDateTime.now(ZoneId.of("GMT")))
|
val date = dateTimeFormatter.format(ZonedDateTime.now(ZoneId.of("GMT")))
|
||||||
val u = URL(url)
|
val u = URL(url)
|
||||||
if (signer?.privateKey == null) {
|
if (signer?.privateKey == null) {
|
||||||
val bodyAsText = httpClient.post(url) {
|
return httpClient.post(url) {
|
||||||
header("Accept", ContentType.Application.Activity)
|
header("Accept", ContentType.Application.Activity)
|
||||||
header("ContentType", ContentType.Application.Activity)
|
header("ContentType", ContentType.Application.Activity)
|
||||||
header("Date", date)
|
header("Date", date)
|
||||||
header("Digest", digest)
|
header("Digest", digest)
|
||||||
setBody(requestBody)
|
setBody(requestBody)
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
return objectMapper.readValue(bodyAsText, responseClass)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val headers = headers {
|
val headers = headers {
|
||||||
|
@ -107,7 +111,7 @@ class APRequestServiceImpl(
|
||||||
), listOf("(request-target)", "date", "host", "digest")
|
), listOf("(request-target)", "date", "host", "digest")
|
||||||
)
|
)
|
||||||
|
|
||||||
val bodyAsText = httpClient.post(url) {
|
return httpClient.post(url) {
|
||||||
headers {
|
headers {
|
||||||
headers {
|
headers {
|
||||||
appendAll(sign.headers)
|
appendAll(sign.headers)
|
||||||
|
@ -116,6 +120,5 @@ class APRequestServiceImpl(
|
||||||
}
|
}
|
||||||
setBody(requestBody)
|
setBody(requestBody)
|
||||||
}.bodyAsText()
|
}.bodyAsText()
|
||||||
return objectMapper.readValue(bodyAsText, responseClass)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@ package dev.usbharu.hideout.service.ap
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import dev.usbharu.hideout.domain.model.ap.Follow
|
import dev.usbharu.hideout.domain.model.ap.Follow
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
||||||
import dev.usbharu.hideout.plugins.postAp
|
|
||||||
import io.ktor.client.*
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier
|
import org.springframework.beans.factory.annotation.Qualifier
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@ -14,8 +12,8 @@ interface APSendFollowService {
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class APSendFollowServiceImpl(
|
class APSendFollowServiceImpl(
|
||||||
private val httpClient: HttpClient,
|
|
||||||
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
|
||||||
|
private val apRequestService: APRequestService,
|
||||||
) : APSendFollowService {
|
) : APSendFollowService {
|
||||||
override suspend fun sendFollow(sendFollowDto: SendFollowDto) {
|
override suspend fun sendFollow(sendFollowDto: SendFollowDto) {
|
||||||
val follow = Follow(
|
val follow = Follow(
|
||||||
|
@ -23,11 +21,7 @@ class APSendFollowServiceImpl(
|
||||||
`object` = sendFollowDto.followTargetUserId.url,
|
`object` = sendFollowDto.followTargetUserId.url,
|
||||||
actor = sendFollowDto.userId.url
|
actor = sendFollowDto.userId.url
|
||||||
)
|
)
|
||||||
httpClient.postAp(
|
|
||||||
urlString = sendFollowDto.followTargetUserId.inbox,
|
apRequestService.apPost(sendFollowDto.followTargetUserId.inbox, follow, sendFollowDto.userId)
|
||||||
username = sendFollowDto.userId.url,
|
|
||||||
jsonLd = follow,
|
|
||||||
objectMapper
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,13 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import dev.usbharu.hideout.domain.model.ap.Object
|
import dev.usbharu.hideout.domain.model.ap.Object
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import dev.usbharu.hideout.repository.UserRepository
|
import dev.usbharu.hideout.repository.UserRepository
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
import dev.usbharu.hideout.service.ap.APRequestService
|
||||||
import io.ktor.client.*
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.client.statement.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier
|
import org.springframework.beans.factory.annotation.Qualifier
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class APResourceResolveServiceImpl(
|
class APResourceResolveServiceImpl(
|
||||||
private val httpClient: HttpClient,
|
private val apRequestService: APRequestService,
|
||||||
private val userRepository: UserRepository,
|
private val userRepository: UserRepository,
|
||||||
private val cacheManager: CacheManager,
|
private val cacheManager: CacheManager,
|
||||||
@Qualifier("activitypub") private val objectMapper: ObjectMapper
|
@Qualifier("activitypub") private val objectMapper: ObjectMapper
|
||||||
|
@ -48,10 +44,7 @@ class APResourceResolveServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun <T : Object> runResolve(url: String, singer: User?, clazz: Class<T>): Object {
|
private suspend fun <T : Object> runResolve(url: String, singer: User?, clazz: Class<T>): Object {
|
||||||
val bodyAsText = httpClient.get(url) {
|
return apRequestService.apGet(url, singer, clazz)
|
||||||
header("Accept", ContentType.Application.Activity)
|
|
||||||
}.bodyAsText()
|
|
||||||
return objectMapper.readValue(bodyAsText, clazz)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun genCacheKey(url: String, singerId: Long?): String {
|
private fun genCacheKey(url: String, singerId: Long?): String {
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
package dev.usbharu.hideout.plugins
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.JsonLd
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.service.user.toPem
|
|
||||||
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 org.mockito.kotlin.any
|
|
||||||
import org.mockito.kotlin.doAnswer
|
|
||||||
import org.mockito.kotlin.mock
|
|
||||||
import utils.JsonObjectMapper.objectMapper
|
|
||||||
import utils.TestApplicationConfig.testApplicationConfig
|
|
||||||
import utils.TestTransaction
|
|
||||||
import java.security.KeyPairGenerator
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class ActivityPubKtTest {
|
|
||||||
@Test
|
|
||||||
fun HttpSignTest() {
|
|
||||||
val userQueryService = mock<UserQueryService> {
|
|
||||||
onBlocking { findByNameAndDomain(any(), any()) } doAnswer {
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(1024)
|
|
||||||
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
User.of(
|
|
||||||
id = 1,
|
|
||||||
name = "test",
|
|
||||||
domain = "localhost",
|
|
||||||
screenName = "test",
|
|
||||||
description = "",
|
|
||||||
password = "",
|
|
||||||
inbox = "https://example.com/inbox",
|
|
||||||
outbox = "https://example.com/outbox",
|
|
||||||
url = "https://example.com",
|
|
||||||
publicKey = "",
|
|
||||||
privateKey = generateKeyPair.private.toPem(),
|
|
||||||
createdAt = Instant.now()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runBlocking {
|
|
||||||
val ktorKeyMap = KtorKeyMap(userQueryService, TestTransaction, testApplicationConfig)
|
|
||||||
|
|
||||||
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()), objectMapper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue