feat: JSON-LDとして正しいJSONを返すように

This commit is contained in:
usbharu 2024-05-14 22:52:23 +09:00
parent f25e9df896
commit 301c07c38e
4 changed files with 59 additions and 21 deletions

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2024 usbharu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.usbharu.hideout.activitypub.domain
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
object Constant {
val context = listOf(
StringOrObject("https://www.w3.org/ns/activitystreams"),
StringOrObject("https://w3id.org/security/v1"),
StringOrObject(
mapOf(
"manuallyApprovesFollowers" to "as:manuallyApprovesFollowers",
"sensitive" to "as:sensitive",
"Hashtag" to "as:Hashtag",
"quoteUrl" to "as:quoteUrl",
"toot" to "http://joinmastodon.org/ns#",
"Emoji" to "toot:Emoji",
"featured" to "toot:featured",
"discoverable" to "toot:discoverable",
"schema" to "http://schema.org#",
"PropertyValue" to "schema:PropertyValue",
"value" to "schema:value",
)
)
)
}

View File

@ -16,8 +16,8 @@
package dev.usbharu.hideout.activitypub.interfaces.api.actor package dev.usbharu.hideout.activitypub.interfaces.api.actor
import dev.usbharu.hideout.activitypub.domain.Constant
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
@ -32,17 +32,7 @@ class UserAPControllerImpl(private val apUserService: APUserService) : UserAPCon
} catch (_: UserNotFoundException) { } catch (_: UserNotFoundException) {
return ResponseEntity.notFound().build() return ResponseEntity.notFound().build()
} }
person.context += listOf( person.context += Constant.context
StringOrObject("https://www.w3.org/ns/activitystreams"),
StringOrObject("https://w3id.org/security/v1"),
StringOrObject(
mapOf(
"manuallyApprovesFollowers" to "as:manuallyApprovesFollowers",
"sensitive" to "as:sensitive",
"Hashtag" to "as:Hashtag"
)
)
)
return ResponseEntity(person, HttpStatus.OK) return ResponseEntity(person, HttpStatus.OK)
} }
} }

View File

@ -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.Constant
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject 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
@ -75,7 +76,7 @@ class APRequestServiceImpl(
date: String, date: String,
u: URL, u: URL,
signer: Actor, signer: Actor,
url: String url: String,
): HttpResponse { ): HttpResponse {
val headers = headers { val headers = headers {
append("Accept", Activity) append("Accept", Activity)
@ -118,7 +119,7 @@ class APRequestServiceImpl(
url: String, url: String,
body: T?, body: T?,
signer: Actor?, signer: Actor?,
responseClass: Class<R> responseClass: Class<R>,
): R { ): R {
val bodyAsText = apPost(url, body, signer) val bodyAsText = apPost(url, body, signer)
return objectMapper.readValue(bodyAsText, responseClass) return objectMapper.readValue(bodyAsText, responseClass)
@ -168,7 +169,7 @@ class APRequestServiceImpl(
url: String, url: String,
date: String?, date: String?,
digest: String, digest: String,
requestBody: String? requestBody: String?,
) = httpClient.post(url) { ) = httpClient.post(url) {
accept(Activity) accept(Activity)
header("Date", date) header("Date", date)
@ -184,7 +185,7 @@ class APRequestServiceImpl(
u: URL, u: URL,
digest: String, digest: String,
signer: Actor, signer: Actor,
requestBody: String? requestBody: String?,
): HttpResponse { ): HttpResponse {
val headers = headers { val headers = headers {
append("Accept", Activity) append("Accept", Activity)
@ -219,10 +220,10 @@ 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<StringOrObject>() val context = mutableListOf<StringOrObject>()
mutableListOf.add(StringOrObject("https://www.w3.org/ns/activitystreams")) context.addAll(Constant.context)
mutableListOf.addAll(body.context) context.addAll(body.context)
body.context = mutableListOf body.context = context
objectMapper.writeValueAsString(body) objectMapper.writeValueAsString(body)
} else { } else {
null null

View File

@ -17,11 +17,14 @@
package dev.usbharu.hideout.application.config package dev.usbharu.hideout.application.config
import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.module.SimpleModule
import com.nimbusds.jose.jwk.JWKSet import com.nimbusds.jose.jwk.JWKSet
import com.nimbusds.jose.jwk.RSAKey import com.nimbusds.jose.jwk.RSAKey
import com.nimbusds.jose.jwk.source.ImmutableJWKSet import com.nimbusds.jose.jwk.source.ImmutableJWKSet
import com.nimbusds.jose.jwk.source.JWKSource import com.nimbusds.jose.jwk.source.JWKSource
import com.nimbusds.jose.proc.SecurityContext import com.nimbusds.jose.proc.SecurityContext
import dev.usbharu.hideout.activitypub.domain.model.StringORObjectSerializer
import dev.usbharu.hideout.activitypub.domain.model.StringOrObject
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.application.infrastructure.springframework.RoleHierarchyAuthorizationManagerFactory import dev.usbharu.hideout.application.infrastructure.springframework.RoleHierarchyAuthorizationManagerFactory
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
@ -295,13 +298,16 @@ class SecurityConfig {
@Primary @Primary
fun jackson2ObjectMapperBuilderCustomizer(): Jackson2ObjectMapperBuilderCustomizer { fun jackson2ObjectMapperBuilderCustomizer(): Jackson2ObjectMapperBuilderCustomizer {
return Jackson2ObjectMapperBuilderCustomizer { return Jackson2ObjectMapperBuilderCustomizer {
it.serializationInclusion(JsonInclude.Include.ALWAYS).serializers() it.serializationInclusion(JsonInclude.Include.ALWAYS)
.modulesToInstall(SimpleModule().addSerializer(StringOrObject::class.java, StringORObjectSerializer()))
.serializers()
} }
} }
@Bean @Bean
fun mappingJackson2HttpMessageConverter(): MappingJackson2HttpMessageConverter { fun mappingJackson2HttpMessageConverter(): MappingJackson2HttpMessageConverter {
val builder = Jackson2ObjectMapperBuilder().serializationInclusion(JsonInclude.Include.NON_NULL) val builder = Jackson2ObjectMapperBuilder().serializationInclusion(JsonInclude.Include.NON_NULL)
builder.modulesToInstall(SimpleModule().addSerializer(StringOrObject::class.java, StringORObjectSerializer()))
return MappingJackson2HttpMessageConverter(builder.build()) return MappingJackson2HttpMessageConverter(builder.build())
} }