mirror of https://github.com/usbharu/Hideout.git
fix: 一部のAP Objectがデシリアライズできなくなっていた問題を修正
This commit is contained in:
parent
faff15f559
commit
bfc5c9e110
|
@ -3,12 +3,11 @@ package dev.usbharu.hideout.activitypub.domain.model
|
||||||
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
|
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
|
||||||
|
|
||||||
open class Key(
|
open class Key(
|
||||||
type: List<String>,
|
|
||||||
override val id: String,
|
override val id: String,
|
||||||
val owner: String,
|
val owner: String,
|
||||||
val publicKeyPem: String
|
val publicKeyPem: String
|
||||||
) : Object(
|
) : Object(
|
||||||
type = add(list = type, type = "Key")
|
type = add(list = emptyList(), type = "Key")
|
||||||
),
|
),
|
||||||
HasId {
|
HasId {
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ constructor(
|
||||||
var outbox: String,
|
var outbox: String,
|
||||||
var url: String,
|
var url: String,
|
||||||
private var icon: Image?,
|
private var icon: Image?,
|
||||||
var publicKey: Key?,
|
var publicKey: Key,
|
||||||
var endpoints: Map<String, String> = emptyMap(),
|
var endpoints: Map<String, String> = emptyMap(),
|
||||||
var followers: String?,
|
var followers: String?,
|
||||||
var following: String?
|
var following: String?
|
||||||
|
|
|
@ -61,7 +61,6 @@ class APUserServiceImpl(
|
||||||
url = "$userUrl/icon.png"
|
url = "$userUrl/icon.png"
|
||||||
),
|
),
|
||||||
publicKey = Key(
|
publicKey = Key(
|
||||||
type = emptyList(),
|
|
||||||
id = userEntity.keyId,
|
id = userEntity.keyId,
|
||||||
owner = userUrl,
|
owner = userUrl,
|
||||||
publicKeyPem = userEntity.publicKey
|
publicKeyPem = userEntity.publicKey
|
||||||
|
@ -129,7 +128,6 @@ class APUserServiceImpl(
|
||||||
url = "$id/icon.png"
|
url = "$id/icon.png"
|
||||||
),
|
),
|
||||||
publicKey = Key(
|
publicKey = Key(
|
||||||
type = emptyList(),
|
|
||||||
id = userEntity.keyId,
|
id = userEntity.keyId,
|
||||||
owner = id,
|
owner = id,
|
||||||
publicKeyPem = userEntity.publicKey
|
publicKeyPem = userEntity.publicKey
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import dev.usbharu.hideout.core.infrastructure.httpsignature.HttpRequestMixIn
|
||||||
|
import dev.usbharu.httpsignature.common.HttpRequest
|
||||||
import dev.usbharu.httpsignature.sign.HttpSignatureSigner
|
import dev.usbharu.httpsignature.sign.HttpSignatureSigner
|
||||||
import dev.usbharu.httpsignature.sign.RsaSha256HttpSignatureSigner
|
import dev.usbharu.httpsignature.sign.RsaSha256HttpSignatureSigner
|
||||||
import org.springframework.beans.factory.annotation.Qualifier
|
import org.springframework.beans.factory.annotation.Qualifier
|
||||||
|
@ -24,12 +26,13 @@ class ActivityPubConfig {
|
||||||
val objectMapper = jacksonObjectMapper()
|
val objectMapper = jacksonObjectMapper()
|
||||||
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
||||||
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
|
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
|
||||||
.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY))
|
.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP))
|
||||||
.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY))
|
.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP))
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
.configure(JsonParser.Feature.ALLOW_COMMENTS, true)
|
.configure(JsonParser.Feature.ALLOW_COMMENTS, true)
|
||||||
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
|
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
|
||||||
.configure(JsonParser.Feature.ALLOW_TRAILING_COMMA, true)
|
.configure(JsonParser.Feature.ALLOW_TRAILING_COMMA, true)
|
||||||
|
.addMixIn(HttpRequest::class.java, HttpRequestMixIn::class.java)
|
||||||
return objectMapper
|
return objectMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package dev.usbharu.hideout.core.infrastructure.httpsignature
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||||
|
import dev.usbharu.httpsignature.common.HttpHeaders
|
||||||
|
import dev.usbharu.httpsignature.common.HttpMethod
|
||||||
|
import dev.usbharu.httpsignature.common.HttpRequest
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
|
||||||
|
@JsonDeserialize(using = HttpRequestDeserializer::class)
|
||||||
|
@JsonSubTypes
|
||||||
|
abstract class HttpRequestMixIn
|
||||||
|
|
||||||
|
class HttpRequestDeserializer : JsonDeserializer<HttpRequest>() {
|
||||||
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): HttpRequest {
|
||||||
|
|
||||||
|
val readTree: JsonNode = p.codec.readTree(p)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return HttpRequest(
|
||||||
|
URL(readTree["url"].textValue()),
|
||||||
|
HttpHeaders(emptyMap()),
|
||||||
|
HttpMethod.valueOf(readTree["method"].textValue())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package dev.usbharu.hideout.activitypub.domain.model
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.application.config.ActivityPubConfig
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class KeySerializeTest {
|
||||||
|
@Test
|
||||||
|
fun Keyのデシリアライズができる() {
|
||||||
|
//language=JSON
|
||||||
|
val trimIndent = """
|
||||||
|
{
|
||||||
|
"id": "https://mastodon.social/users/Gargron#main-key",
|
||||||
|
"owner": "https://mastodon.social/users/Gargron",
|
||||||
|
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvXc4vkECU2/CeuSo1wtn\nFoim94Ne1jBMYxTZ9wm2YTdJq1oiZKif06I2fOqDzY/4q/S9uccrE9Bkajv1dnkO\nVm31QjWlhVpSKynVxEWjVBO5Ienue8gND0xvHIuXf87o61poqjEoepvsQFElA5ym\novljWGSA/jpj7ozygUZhCXtaS2W5AD5tnBQUpcO0lhItYPYTjnmzcc4y2NbJV8hz\n2s2G8qKv8fyimE23gY1XrPJg+cRF+g4PqFXujjlJ7MihD9oqtLGxbu7o1cifTn3x\nBfIdPythWu5b4cujNsB3m3awJjVmx+MHQ9SugkSIYXV0Ina77cTNS0M2PYiH1PFR\nTwIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
val readValue = objectMapper.readValue<Key>(trimIndent)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package dev.usbharu.hideout.activitypub.domain.model
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.application.config.ActivityPubConfig
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class PersonSerializeTest {
|
||||||
|
@Test
|
||||||
|
fun MastodonのPersonのデシリアライズができる() {
|
||||||
|
val personString = """
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1"
|
||||||
|
],
|
||||||
|
"id": "https://mastodon.social/users/Gargron",
|
||||||
|
"type": "Person",
|
||||||
|
"following": "https://mastodon.social/users/Gargron/following",
|
||||||
|
"followers": "https://mastodon.social/users/Gargron/followers",
|
||||||
|
"inbox": "https://mastodon.social/users/Gargron/inbox",
|
||||||
|
"outbox": "https://mastodon.social/users/Gargron/outbox",
|
||||||
|
"featured": "https://mastodon.social/users/Gargron/collections/featured",
|
||||||
|
"featuredTags": "https://mastodon.social/users/Gargron/collections/tags",
|
||||||
|
"preferredUsername": "Gargron",
|
||||||
|
"name": "Eugen Rochko",
|
||||||
|
"summary": "\u003cp\u003eFounder, CEO and lead developer \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://mastodon.social/@Mastodon\" class=\"u-url mention\"\u003e@\u003cspan\u003eMastodon\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e, Germany.\u003c/p\u003e",
|
||||||
|
"url": "https://mastodon.social/@Gargron",
|
||||||
|
"manuallyApprovesFollowers": false,
|
||||||
|
"discoverable": true,
|
||||||
|
"published": "2016-03-16T00:00:00Z",
|
||||||
|
"devices": "https://mastodon.social/users/Gargron/collections/devices",
|
||||||
|
"alsoKnownAs": [
|
||||||
|
"https://tooting.ai/users/Gargron"
|
||||||
|
],
|
||||||
|
"publicKey": {
|
||||||
|
"id": "https://mastodon.social/users/Gargron#main-key",
|
||||||
|
"owner": "https://mastodon.social/users/Gargron",
|
||||||
|
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvXc4vkECU2/CeuSo1wtn\nFoim94Ne1jBMYxTZ9wm2YTdJq1oiZKif06I2fOqDzY/4q/S9uccrE9Bkajv1dnkO\nVm31QjWlhVpSKynVxEWjVBO5Ienue8gND0xvHIuXf87o61poqjEoepvsQFElA5ym\novljWGSA/jpj7ozygUZhCXtaS2W5AD5tnBQUpcO0lhItYPYTjnmzcc4y2NbJV8hz\n2s2G8qKv8fyimE23gY1XrPJg+cRF+g4PqFXujjlJ7MihD9oqtLGxbu7o1cifTn3x\nBfIdPythWu5b4cujNsB3m3awJjVmx+MHQ9SugkSIYXV0Ina77cTNS0M2PYiH1PFR\nTwIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||||
|
},
|
||||||
|
"tag": [],
|
||||||
|
"attachment": [
|
||||||
|
{
|
||||||
|
"type": "PropertyValue",
|
||||||
|
"name": "Patreon",
|
||||||
|
"value": "\u003ca href=\"https://www.patreon.com/mastodon\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://www.\u003c/span\u003e\u003cspan class=\"\"\u003epatreon.com/mastodon\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "PropertyValue",
|
||||||
|
"name": "GitHub",
|
||||||
|
"value": "\u003ca href=\"https://github.com/Gargron\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003egithub.com/Gargron\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"endpoints": {
|
||||||
|
"sharedInbox": "https://mastodon.social/inbox"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"type": "Image",
|
||||||
|
"mediaType": "image/jpeg",
|
||||||
|
"url": "https://files.mastodon.social/accounts/avatars/000/000/001/original/dc4286ceb8fab734.jpg"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "Image",
|
||||||
|
"mediaType": "image/jpeg",
|
||||||
|
"url": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
|
||||||
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
val readValue = objectMapper.readValue<Person>(personString)
|
||||||
|
}
|
||||||
|
}
|
|
@ -126,7 +126,6 @@ class APNoteServiceImplTest {
|
||||||
url = user.url + "/icon.png"
|
url = user.url + "/icon.png"
|
||||||
),
|
),
|
||||||
publicKey = Key(
|
publicKey = Key(
|
||||||
type = emptyList(),
|
|
||||||
id = user.keyId,
|
id = user.keyId,
|
||||||
owner = user.url,
|
owner = user.url,
|
||||||
publicKeyPem = user.publicKey
|
publicKeyPem = user.publicKey
|
||||||
|
@ -245,7 +244,6 @@ class APNoteServiceImplTest {
|
||||||
url = user.url + "/icon.png"
|
url = user.url + "/icon.png"
|
||||||
),
|
),
|
||||||
publicKey = Key(
|
publicKey = Key(
|
||||||
type = emptyList(),
|
|
||||||
id = user.keyId,
|
id = user.keyId,
|
||||||
owner = user.url,
|
owner = user.url,
|
||||||
publicKeyPem = user.publicKey
|
publicKeyPem = user.publicKey
|
||||||
|
|
Loading…
Reference in New Issue