mirror of https://github.com/usbharu/Hideout.git
wip
This commit is contained in:
parent
ae43b5e793
commit
8f553d3ecd
|
@ -31,18 +31,18 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize
|
||||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
|
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
|
||||||
open class JsonLd {
|
open class JsonLd {
|
||||||
@JsonProperty("@context")
|
@JsonProperty("@context")
|
||||||
@JsonDeserialize(contentUsing = ContextDeserializer::class)
|
@JsonDeserialize(contentUsing = StringOrObjectDeserializer::class)
|
||||||
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, using = ContextSerializer::class)
|
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, contentUsing = StringORObjectSerializer::class)
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
var context: List<StringOrObject> = emptyList()
|
var context: List<StringOrObject> = emptyList()
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value.filter { it.isEmpty() }
|
field = value.filterNot { it.isEmpty() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
constructor(context: List<StringOrObject?>?) {
|
constructor(context: List<StringOrObject?>?) {
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
this.context = context.filterNotNull().filter { it.isEmpty() }
|
this.context = context.filterNotNull().filterNot { it.isEmpty() }
|
||||||
} else {
|
} else {
|
||||||
this.context = emptyList()
|
this.context = emptyList()
|
||||||
}
|
}
|
||||||
|
@ -89,17 +89,13 @@ class ContextSerializer : JsonSerializer<List<StringOrObject>>() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (value.size == 1) {
|
if (value.size == 1) {
|
||||||
gen?.writeString(value[0])
|
serializers.findValueSerializer(StringOrObject::class.java).serialize(value[0], gen, serializers)
|
||||||
} else {
|
} else {
|
||||||
gen?.writeStartArray()
|
gen?.writeStartArray()
|
||||||
value.forEach {
|
value.forEach {
|
||||||
gen?.writeString(it)
|
serializers.findValueSerializer(StringOrObject::class.java).serialize(it, gen, serializers)
|
||||||
}
|
}
|
||||||
gen?.writeEndArray()
|
gen?.writeEndArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serialize(value: List<StringOrObject>?, gen: JsonGenerator?, serializers: SerializerProvider?) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,14 +50,19 @@ open class StringOrObject {
|
||||||
|
|
||||||
|
|
||||||
class StringOrObjectDeserializer : JsonDeserializer<StringOrObject>() {
|
class StringOrObjectDeserializer : JsonDeserializer<StringOrObject>() {
|
||||||
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): StringOrObject {
|
override fun deserialize(p: JsonParser?, ctxt: DeserializationContext): StringOrObject {
|
||||||
val readTree: JsonNode = p?.codec?.readTree(p) ?: return StringOrObject("")
|
val readTree: JsonNode = p?.codec?.readTree(p) ?: return StringOrObject("")
|
||||||
return if (readTree.isValueNode) {
|
return if (readTree.isValueNode) {
|
||||||
StringOrObject(readTree.textValue())
|
StringOrObject(readTree.textValue())
|
||||||
} else {
|
} else {
|
||||||
|
val map: Map<String, String> = ctxt.readTreeAsValue<Map<String, String>>(
|
||||||
|
readTree,
|
||||||
|
ctxt.typeFactory.constructType(object : TypeReference<Map<String, String>>() {})
|
||||||
|
)
|
||||||
|
println(readTree.toPrettyString())
|
||||||
|
|
||||||
val map = p.readValueAs<Map<String, String>>(object : TypeReference<Map<String, String>>() {})
|
// val map = p.codec.readValue<Map<String, String>>(p,object : TypeReference<Map<String, String>>() {})
|
||||||
|
println(map)
|
||||||
StringOrObject(map)
|
StringOrObject(map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,8 +77,10 @@ class StringORObjectSerializer : JsonSerializer<StringOrObject>() {
|
||||||
}
|
}
|
||||||
if (value.contextString != null) {
|
if (value.contextString != null) {
|
||||||
gen?.writeString(value.contextString)
|
gen?.writeString(value.contextString)
|
||||||
|
println("serialize string")
|
||||||
} else {
|
} else {
|
||||||
serializers.defaultSerializeValue(value.contextObject, gen)
|
serializers.defaultSerializeValue(value.contextObject, gen)
|
||||||
|
println("serialize string")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package dev.usbharu.hideout.activitypub.interfaces.api.actor
|
package dev.usbharu.hideout.activitypub.interfaces.api.actor
|
||||||
|
|
||||||
import dev.usbharu.hideout.activitypub.domain.model.Person
|
import dev.usbharu.hideout.activitypub.domain.model.Person
|
||||||
|
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
|
||||||
import dev.usbharu.hideout.activitypub.service.objects.user.APUserService
|
import dev.usbharu.hideout.activitypub.service.objects.user.APUserService
|
||||||
import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException
|
import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException
|
||||||
import org.springframework.http.HttpStatus
|
import org.springframework.http.HttpStatus
|
||||||
|
@ -31,7 +32,7 @@ class UserAPControllerImpl(private val apUserService: APUserService) : UserAPCon
|
||||||
} catch (_: UserNotFoundException) {
|
} catch (_: UserNotFoundException) {
|
||||||
return ResponseEntity.notFound().build()
|
return ResponseEntity.notFound().build()
|
||||||
}
|
}
|
||||||
person.context += listOf("https://www.w3.org/ns/activitystreams")
|
person.context += listOf(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
return ResponseEntity(person, HttpStatus.OK)
|
return ResponseEntity(person, HttpStatus.OK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package dev.usbharu.hideout.activitypub.service.common
|
package dev.usbharu.hideout.activitypub.service.common
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
|
||||||
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
|
import dev.usbharu.hideout.activitypub.domain.model.objects.Object
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||||
import dev.usbharu.hideout.util.Base64Util
|
import dev.usbharu.hideout.util.Base64Util
|
||||||
|
@ -218,8 +219,8 @@ class APRequestServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : Object> addContextIfNotNull(body: T?) = if (body != null) {
|
private fun <T : Object> addContextIfNotNull(body: T?) = if (body != null) {
|
||||||
val mutableListOf = mutableListOf<String>()
|
val mutableListOf = mutableListOf<StringOrObject>()
|
||||||
mutableListOf.add("https://www.w3.org/ns/activitystreams")
|
mutableListOf.add(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
mutableListOf.addAll(body.context)
|
mutableListOf.addAll(body.context)
|
||||||
body.context = mutableListOf
|
body.context = mutableListOf
|
||||||
objectMapper.writeValueAsString(body)
|
objectMapper.writeValueAsString(body)
|
||||||
|
|
|
@ -49,6 +49,7 @@ class ActivityPubConfig {
|
||||||
.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)
|
.addMixIn(HttpRequest::class.java, HttpRequestMixIn::class.java)
|
||||||
|
|
||||||
return objectMapper
|
return objectMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,11 @@ class DeleteSerializeTest {
|
||||||
),
|
),
|
||||||
published = "2023-11-02T15:30:34.160Z",
|
published = "2023-11-02T15:30:34.160Z",
|
||||||
)
|
)
|
||||||
expected.context = listOf("https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", "")
|
expected.context = listOf(
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams"),
|
||||||
|
StringOrObject("https://w3id.org/security/v1"),
|
||||||
|
StringOrObject("")
|
||||||
|
)
|
||||||
assertEquals(expected, readValue)
|
assertEquals(expected, readValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
val readValue = objectMapper.readValue<JsonLd>(json)
|
val readValue = objectMapper.readValue<JsonLd>(json)
|
||||||
|
|
||||||
assertEquals(JsonLd(listOf("https://example.com")), readValue)
|
assertEquals(JsonLd(listOf(StringOrObject("https://example.com"))), readValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -43,7 +43,14 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
val readValue = objectMapper.readValue<JsonLd>(json)
|
val readValue = objectMapper.readValue<JsonLd>(json)
|
||||||
|
|
||||||
assertEquals(JsonLd(listOf("https://example.com", "https://www.w3.org/ns/activitystreams")), readValue)
|
assertEquals(
|
||||||
|
JsonLd(
|
||||||
|
listOf(
|
||||||
|
StringOrObject("https://example.com"),
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams")
|
||||||
|
)
|
||||||
|
), readValue
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -67,7 +74,14 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
val readValue = objectMapper.readValue<JsonLd>(json)
|
val readValue = objectMapper.readValue<JsonLd>(json)
|
||||||
|
|
||||||
assertEquals(JsonLd(listOf("https://example.com", "https://www.w3.org/ns/activitystreams")), readValue)
|
assertEquals(
|
||||||
|
JsonLd(
|
||||||
|
listOf(
|
||||||
|
StringOrObject("https://example.com"),
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams")
|
||||||
|
)
|
||||||
|
), readValue
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -79,7 +93,7 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
val readValue = objectMapper.readValue<JsonLd>(json)
|
val readValue = objectMapper.readValue<JsonLd>(json)
|
||||||
|
|
||||||
assertEquals(JsonLd(emptyList()), readValue)
|
assertEquals(JsonLd(listOf(StringOrObject(mapOf("hoge" to "fuga")))), readValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -91,7 +105,15 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
val readValue = objectMapper.readValue<JsonLd>(json)
|
val readValue = objectMapper.readValue<JsonLd>(json)
|
||||||
|
|
||||||
assertEquals(JsonLd(listOf("https://example.com", "https://www.w3.org/ns/activitystreams")), readValue)
|
assertEquals(
|
||||||
|
JsonLd(
|
||||||
|
listOf(
|
||||||
|
StringOrObject("https://example.com"),
|
||||||
|
StringOrObject(mapOf("hoge" to "fuga")),
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams")
|
||||||
|
)
|
||||||
|
), readValue
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -130,7 +152,7 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun contextが文字列のとき文字列としてシリアライズされる() {
|
fun contextが文字列のとき文字列としてシリアライズされる() {
|
||||||
val jsonLd = JsonLd(listOf("https://example.com"))
|
val jsonLd = JsonLd(listOf(StringOrObject("https://example.com")))
|
||||||
|
|
||||||
val objectMapper = ActivityPubConfig().objectMapper()
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
@ -141,7 +163,12 @@ class JsonLdSerializeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun contextが文字列の配列のとき配列としてシリアライズされる() {
|
fun contextが文字列の配列のとき配列としてシリアライズされる() {
|
||||||
val jsonLd = JsonLd(listOf("https://example.com", "https://www.w3.org/ns/activitystreams"))
|
val jsonLd = JsonLd(
|
||||||
|
listOf(
|
||||||
|
StringOrObject("https://example.com"),
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val objectMapper = ActivityPubConfig().objectMapper()
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
|
|
@ -183,8 +183,8 @@ class NoteSerializeTest {
|
||||||
)
|
)
|
||||||
|
|
||||||
expected.context = listOf(
|
expected.context = listOf(
|
||||||
"https://www.w3.org/ns/activitystreams",
|
StringOrObject("https://www.w3.org/ns/activitystreams"),
|
||||||
"https://w3id.org/security/v1"
|
StringOrObject("https://w3id.org/security/v1")
|
||||||
)
|
)
|
||||||
|
|
||||||
val note = objectMapper.readValue<Note>(json)
|
val note = objectMapper.readValue<Note>(json)
|
||||||
|
|
|
@ -72,7 +72,12 @@ class RejectTest {
|
||||||
actor = "https://test-hideout.usbharu.dev/users/test-user2",
|
actor = "https://test-hideout.usbharu.dev/users/test-user2",
|
||||||
id = "https://misskey.usbharu.dev/follows/9mxh6mawru/97ws8y3rj6"
|
id = "https://misskey.usbharu.dev/follows/9mxh6mawru/97ws8y3rj6"
|
||||||
)
|
)
|
||||||
).apply { context = listOf("https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1") }
|
).apply {
|
||||||
|
context = listOf(
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams"),
|
||||||
|
StringOrObject("https://w3id.org/security/v1")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
assertThat(reject).isEqualTo(expected)
|
assertThat(reject).isEqualTo(expected)
|
||||||
}
|
}
|
||||||
|
@ -88,7 +93,12 @@ class RejectTest {
|
||||||
apObject = "https://misskey.usbharu.dev/users/97ws8y3rj6",
|
apObject = "https://misskey.usbharu.dev/users/97ws8y3rj6",
|
||||||
actor = "https://test-hideout.usbharu.dev/users/test-user2"
|
actor = "https://test-hideout.usbharu.dev/users/test-user2"
|
||||||
)
|
)
|
||||||
).apply { context = listOf("https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1") }
|
).apply {
|
||||||
|
context = listOf(
|
||||||
|
StringOrObject("https://www.w3.org/ns/activitystreams"),
|
||||||
|
StringOrObject("https://w3id.org/security/v1")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val objectMapper = ActivityPubConfig().objectMapper()
|
val objectMapper = ActivityPubConfig().objectMapper()
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package dev.usbharu.hideout.activitypub.service.common
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.activitypub.domain.model.Follow
|
import dev.usbharu.hideout.activitypub.domain.model.Follow
|
||||||
|
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
|
||||||
import dev.usbharu.hideout.util.Base64Util
|
import dev.usbharu.hideout.util.Base64Util
|
||||||
import dev.usbharu.httpsignature.common.HttpHeaders
|
import dev.usbharu.httpsignature.common.HttpHeaders
|
||||||
import dev.usbharu.httpsignature.common.HttpMethod
|
import dev.usbharu.httpsignature.common.HttpMethod
|
||||||
|
@ -173,7 +174,7 @@ class APRequestServiceImplTest {
|
||||||
val apRequestServiceImpl = APRequestServiceImpl(HttpClient(MockEngine {
|
val apRequestServiceImpl = APRequestServiceImpl(HttpClient(MockEngine {
|
||||||
val readValue = objectMapper.readValue<Follow>(it.body.toByteArray())
|
val readValue = objectMapper.readValue<Follow>(it.body.toByteArray())
|
||||||
|
|
||||||
assertThat(readValue.context).contains("https://www.w3.org/ns/activitystreams")
|
assertThat(readValue.context).contains(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
|
|
||||||
respondOk("{}")
|
respondOk("{}")
|
||||||
}), objectMapper, mock(), dateTimeFormatter)
|
}), objectMapper, mock(), dateTimeFormatter)
|
||||||
|
@ -205,7 +206,7 @@ class APRequestServiceImplTest {
|
||||||
val src = it.body.toByteArray()
|
val src = it.body.toByteArray()
|
||||||
val readValue = objectMapper.readValue<Follow>(src)
|
val readValue = objectMapper.readValue<Follow>(src)
|
||||||
|
|
||||||
assertThat(readValue.context).contains("https://www.w3.org/ns/activitystreams")
|
assertThat(readValue.context).contains(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
|
|
||||||
val map = it.headers.toMap()
|
val map = it.headers.toMap()
|
||||||
assertThat(map).containsKey("Date")
|
assertThat(map).containsKey("Date")
|
||||||
|
@ -238,7 +239,7 @@ class APRequestServiceImplTest {
|
||||||
val src = it.body.toByteArray()
|
val src = it.body.toByteArray()
|
||||||
val readValue = objectMapper.readValue<Follow>(src)
|
val readValue = objectMapper.readValue<Follow>(src)
|
||||||
|
|
||||||
assertThat(readValue.context).contains("https://www.w3.org/ns/activitystreams")
|
assertThat(readValue.context).contains(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
|
|
||||||
val map = it.headers.toMap()
|
val map = it.headers.toMap()
|
||||||
assertThat(map).containsKey("Date")
|
assertThat(map).containsKey("Date")
|
||||||
|
@ -279,7 +280,7 @@ class APRequestServiceImplTest {
|
||||||
val src = it.body.toByteArray()
|
val src = it.body.toByteArray()
|
||||||
val readValue = objectMapper.readValue<Follow>(src)
|
val readValue = objectMapper.readValue<Follow>(src)
|
||||||
|
|
||||||
assertThat(readValue.context).contains("https://www.w3.org/ns/activitystreams")
|
assertThat(readValue.context).contains(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
|
|
||||||
val map = it.headers.toMap()
|
val map = it.headers.toMap()
|
||||||
assertThat(map).containsKey("Date")
|
assertThat(map).containsKey("Date")
|
||||||
|
@ -340,7 +341,7 @@ class APRequestServiceImplTest {
|
||||||
val src = it.body.toByteArray()
|
val src = it.body.toByteArray()
|
||||||
val readValue = objectMapper.readValue<Follow>(src)
|
val readValue = objectMapper.readValue<Follow>(src)
|
||||||
|
|
||||||
assertThat(readValue.context).contains("https://www.w3.org/ns/activitystreams")
|
assertThat(readValue.context).contains(StringOrObject("https://www.w3.org/ns/activitystreams"))
|
||||||
|
|
||||||
respondOk(src.decodeToString())
|
respondOk(src.decodeToString())
|
||||||
}), objectMapper, mock(), dateTimeFormatter)
|
}), objectMapper, mock(), dateTimeFormatter)
|
||||||
|
|
Loading…
Reference in New Issue