refactor: objectをapObjectにしてエスケープの必要をなくした

This commit is contained in:
usbharu 2023-11-28 12:34:56 +09:00
parent 34d8eabea1
commit 259ff937dc
19 changed files with 90 additions and 64 deletions

View File

@ -1,6 +1,7 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
@ -8,13 +9,13 @@ import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Accept @JsonCreator constructor( open class Accept @JsonCreator constructor(
type: List<String> = emptyList(), type: List<String> = emptyList(),
override val name: String, override val name: String,
@JsonDeserialize(using = ObjectDeserializer::class) @Suppress("VariableNaming") var `object`: Object?, @JsonDeserialize(using = ObjectDeserializer::class)
@JsonProperty("object")
val apObject: Object,
override val actor: String override val actor: String
) : Object( ) : Object(
type = add(type, "Accept") type = add(type, "Accept")
), ), HasActor, HasName {
HasActor,
HasName {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@ -23,22 +24,27 @@ open class Accept @JsonCreator constructor(
other as Accept other as Accept
if (`object` != other.`object`) return false
if (actor != other.actor) return false
if (name != other.name) return false if (name != other.name) return false
if (apObject != other.apObject) return false
if (actor != other.actor) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + actor.hashCode()
result = 31 * result + name.hashCode() result = 31 * result + name.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode()
return result return result
} }
override fun toString(): String { override fun toString(): String {
return "Accept(" + "`object`=$`object`, " + "actor='$actor', " + "name='$name'" + ")" + " ${super.toString()}" return "Accept(" +
"name='$name', " +
"apObject=$apObject, " +
"actor='$actor'" +
")" +
" ${super.toString()}"
} }
} }

View File

@ -1,5 +1,6 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
@ -8,8 +9,8 @@ open class Create(
type: List<String> = emptyList(), type: List<String> = emptyList(),
override val name: String, override val name: String,
@JsonDeserialize(using = ObjectDeserializer::class) @JsonDeserialize(using = ObjectDeserializer::class)
@Suppress("VariableNaming") @JsonProperty("object")
val `object`: Object, val apObject: Object,
override val actor: String, override val actor: String,
override val id: String, override val id: String,
val to: List<String> = emptyList(), val to: List<String> = emptyList(),
@ -28,27 +29,36 @@ open class Create(
other as Create other as Create
if (`object` != other.`object`) return false
if (to != other.to) return false
if (cc != other.cc) return false
if (name != other.name) return false if (name != other.name) return false
if (apObject != other.apObject) return false
if (actor != other.actor) return false if (actor != other.actor) return false
if (id != other.id) return false if (id != other.id) return false
if (to != other.to) return false
if (cc != other.cc) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + to.hashCode()
result = 31 * result + cc.hashCode()
result = 31 * result + name.hashCode() result = 31 * result + name.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode() result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode() result = 31 * result + id.hashCode()
result = 31 * result + to.hashCode()
result = 31 * result + cc.hashCode()
return result return result
} }
override fun toString(): String = override fun toString(): String {
"Create(`object`=$`object`, to=$to, cc=$cc, name='$name', actor='$actor', id='$id') ${super.toString()}" return "Create(" +
"name='$name', " +
"apObject=$apObject, " +
"actor='$actor', " +
"id='$id', " +
"to=$to, " +
"cc=$cc" +
")" +
" ${super.toString()}"
}
} }

View File

@ -1,13 +1,14 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
open class Delete : Object, HasId, HasActor { open class Delete : Object, HasId, HasActor {
@JsonDeserialize(using = ObjectDeserializer::class) @JsonDeserialize(using = ObjectDeserializer::class)
@Suppress("VariableNaming") @JsonProperty("object")
val `object`: Object val apObject: Object
val published: String val published: String
override val actor: String override val actor: String
override val id: String override val id: String
@ -19,7 +20,7 @@ open class Delete : Object, HasId, HasActor {
`object`: Object, `object`: Object,
published: String published: String
) : super(add(type, "Delete")) { ) : super(add(type, "Delete")) {
this.`object` = `object` this.apObject = `object`
this.published = published this.published = published
this.actor = actor this.actor = actor
this.id = id this.id = id
@ -32,7 +33,7 @@ open class Delete : Object, HasId, HasActor {
other as Delete other as Delete
if (`object` != other.`object`) return false if (apObject != other.apObject) return false
if (published != other.published) return false if (published != other.published) return false
if (actor != other.actor) return false if (actor != other.actor) return false
if (id != other.id) return false if (id != other.id) return false
@ -42,7 +43,7 @@ open class Delete : Object, HasId, HasActor {
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0) result = 31 * result + (apObject?.hashCode() ?: 0)
result = 31 * result + (published?.hashCode() ?: 0) result = 31 * result + (published?.hashCode() ?: 0)
result = 31 * result + actor.hashCode() result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode() result = 31 * result + id.hashCode()
@ -50,5 +51,5 @@ open class Delete : Object, HasId, HasActor {
} }
override fun toString(): String = override fun toString(): String =
"Delete(`object`=$`object`, published=$published, actor='$actor', id='$id') ${super.toString()}" "Delete(`object`=$apObject, published=$published, actor='$actor', id='$id') ${super.toString()}"
} }

View File

@ -1,10 +1,11 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
open class Follow( open class Follow(
type: List<String> = emptyList(), type: List<String> = emptyList(),
@Suppress("VariableNaming") val `object`: String, @JsonProperty("object") val apObject: String,
override val actor: String override val actor: String
) : Object( ) : Object(
type = add(type, "Follow") type = add(type, "Follow")
@ -18,7 +19,7 @@ open class Follow(
other as Follow other as Follow
if (`object` != other.`object`) return false if (apObject != other.apObject) return false
if (actor != other.actor) return false if (actor != other.actor) return false
return true return true
@ -26,10 +27,10 @@ open class Follow(
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + `object`.hashCode() result = 31 * result + apObject.hashCode()
result = 31 * result + actor.hashCode() result = 31 * result + actor.hashCode()
return result return result
} }
override fun toString(): String = "Follow(`object`=$`object`, actor='$actor') ${super.toString()}" override fun toString(): String = "Follow(`object`=$apObject, actor='$actor') ${super.toString()}"
} }

View File

@ -1,5 +1,6 @@
package dev.usbharu.hideout.activitypub.domain.model package dev.usbharu.hideout.activitypub.domain.model
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.activitypub.domain.model.objects.Object
import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectDeserializer
@ -8,7 +9,7 @@ open class Like(
type: List<String> = emptyList(), type: List<String> = emptyList(),
override val actor: String, override val actor: String,
override val id: String, override val id: String,
@Suppress("VariableNaming") val `object`: String, @JsonProperty("object") val apObject: String,
val content: String, val content: String,
@JsonDeserialize(contentUsing = ObjectDeserializer::class) val tag: List<Object> = emptyList() @JsonDeserialize(contentUsing = ObjectDeserializer::class) val tag: List<Object> = emptyList()
) : Object( ) : Object(
@ -24,26 +25,33 @@ open class Like(
other as Like other as Like
if (`object` != other.`object`) return false
if (content != other.content) return false
if (tag != other.tag) return false
if (actor != other.actor) return false if (actor != other.actor) return false
if (id != other.id) return false if (id != other.id) return false
if (apObject != other.apObject) return false
if (content != other.content) return false
if (tag != other.tag) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = super.hashCode() var result = super.hashCode()
result = 31 * result + (`object`?.hashCode() ?: 0)
result = 31 * result + (content?.hashCode() ?: 0)
result = 31 * result + tag.hashCode()
result = 31 * result + actor.hashCode() result = 31 * result + actor.hashCode()
result = 31 * result + id.hashCode() result = 31 * result + id.hashCode()
result = 31 * result + apObject.hashCode()
result = 31 * result + content.hashCode()
result = 31 * result + tag.hashCode()
return result return result
} }
override fun toString(): String { override fun toString(): String {
return "Like(`object`=$`object`, content=$content, tag=$tag, actor='$actor', id='$id') ${super.toString()}" return "Like(" +
"actor='$actor', " +
"id='$id', " +
"apObject='$apObject', " +
"content='$content', " +
"tag=$tag" +
")" +
" ${super.toString()}"
} }
} }

View File

@ -20,7 +20,7 @@ class ApAcceptProcessor(
AbstractActivityPubProcessor<Accept>(transaction) { AbstractActivityPubProcessor<Accept>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Accept>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Accept>) {
val value = activity.activity.`object` ?: throw IllegalActivityPubObjectException("object is null") val value = activity.activity.apObject ?: throw IllegalActivityPubObjectException("object is null")
if (value.type.contains("Follow").not()) { if (value.type.contains("Follow").not()) {
logger.warn("FAILED Activity type isn't Follow.") logger.warn("FAILED Activity type isn't Follow.")
@ -29,7 +29,7 @@ class ApAcceptProcessor(
val follow = value as Follow val follow = value as Follow
val userUrl = follow.`object` val userUrl = follow.apObject
val followerUrl = follow.actor val followerUrl = follow.actor
val user = userQueryService.findByUrl(userUrl) val user = userQueryService.findByUrl(userUrl)

View File

@ -33,7 +33,7 @@ class ApSendCreateServiceImpl(
val note = noteQueryService.findById(post.id).first val note = noteQueryService.findById(post.id).first
val create = Create( val create = Create(
name = "Create Note", name = "Create Note",
`object` = note, apObject = note,
actor = note.attributedTo, actor = note.attributedTo,
id = "${applicationConfig.url}/create/note/${post.id}" id = "${applicationConfig.url}/create/note/${post.id}"
) )

View File

@ -13,7 +13,7 @@ import org.springframework.stereotype.Service
class CreateActivityProcessor(transaction: Transaction, private val apNoteService: APNoteService) : class CreateActivityProcessor(transaction: Transaction, private val apNoteService: APNoteService) :
AbstractActivityPubProcessor<Create>(transaction) { AbstractActivityPubProcessor<Create>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Create>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Create>) {
apNoteService.fetchNote(activity.activity.`object` as Note) apNoteService.fetchNote(activity.activity.apObject as Note)
} }
override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Create override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Create

View File

@ -18,7 +18,7 @@ class APDeleteProcessor(
) : ) :
AbstractActivityPubProcessor<Delete>(transaction) { AbstractActivityPubProcessor<Delete>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Delete>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Delete>) {
val value = activity.activity.`object` val value = activity.activity.apObject
if (value !is HasId) { if (value !is HasId) {
throw IllegalActivityPubObjectException("object hasn't id") throw IllegalActivityPubObjectException("object hasn't id")
} }

View File

@ -17,13 +17,13 @@ class APFollowProcessor(
) : ) :
AbstractActivityPubProcessor<Follow>(transaction) { AbstractActivityPubProcessor<Follow>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Follow>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Follow>) {
logger.info("FOLLOW from: {} to {}", activity.activity.actor, activity.activity.`object`) logger.info("FOLLOW from: {} to {}", activity.activity.actor, activity.activity.apObject)
// inboxをジョブキューに乗せているので既に不要だが、フォロー承認制アカウントを実装する際に必要なので残す // inboxをジョブキューに乗せているので既に不要だが、フォロー承認制アカウントを実装する際に必要なので残す
val jobProps = ReceiveFollowJobParam( val jobProps = ReceiveFollowJobParam(
activity.activity.actor, activity.activity.actor,
objectMapper.writeValueAsString(activity.activity), objectMapper.writeValueAsString(activity.activity),
activity.activity.`object` activity.activity.apObject
) )
jobQueueParentService.scheduleTypeSafe(ReceiveFollowJob, jobProps) jobQueueParentService.scheduleTypeSafe(ReceiveFollowJob, jobProps)
} }

View File

@ -39,7 +39,7 @@ class APReceiveFollowJobProcessor(
url = urlString, url = urlString,
body = Accept( body = Accept(
name = "Follow", name = "Follow",
`object` = follow, apObject = follow,
actor = param.targetActor actor = param.targetActor
), ),
signer = signer signer = signer

View File

@ -18,11 +18,11 @@ class APReceiveFollowServiceImpl(
@Qualifier("activitypub") private val objectMapper: ObjectMapper @Qualifier("activitypub") private val objectMapper: ObjectMapper
) : APReceiveFollowService { ) : APReceiveFollowService {
override suspend fun receiveFollow(follow: Follow) { override suspend fun receiveFollow(follow: Follow) {
logger.info("FOLLOW from: {} to: {}", follow.actor, follow.`object`) logger.info("FOLLOW from: {} to: {}", follow.actor, follow.apObject)
jobQueueParentService.schedule(ReceiveFollowJob) { jobQueueParentService.schedule(ReceiveFollowJob) {
props[ReceiveFollowJob.actor] = follow.actor props[ReceiveFollowJob.actor] = follow.actor
props[ReceiveFollowJob.follow] = objectMapper.writeValueAsString(follow) props[ReceiveFollowJob.follow] = objectMapper.writeValueAsString(follow)
props[ReceiveFollowJob.targetActor] = follow.`object` props[ReceiveFollowJob.targetActor] = follow.apObject
} }
return return
} }

View File

@ -15,7 +15,7 @@ class APSendFollowServiceImpl(
) : APSendFollowService { ) : APSendFollowService {
override suspend fun sendFollow(sendFollowDto: SendFollowDto) { override suspend fun sendFollow(sendFollowDto: SendFollowDto) {
val follow = Follow( val follow = Follow(
`object` = sendFollowDto.followTargetUserId.url, apObject = sendFollowDto.followTargetUserId.url,
actor = sendFollowDto.userId.url actor = sendFollowDto.userId.url
) )

View File

@ -23,7 +23,7 @@ class APLikeProcessor(
val actor = activity.activity.actor val actor = activity.activity.actor
val content = activity.activity.content val content = activity.activity.content
val target = activity.activity.`object` val target = activity.activity.apObject
val personWithEntity = apUserService.fetchPersonWithEntity(actor) val personWithEntity = apUserService.fetchPersonWithEntity(actor)

View File

@ -22,7 +22,7 @@ class ApReactionJobProcessor(
param.inbox, param.inbox,
Like( Like(
actor = param.actor, actor = param.actor,
`object` = param.postUrl, apObject = param.postUrl,
id = "${applicationConfig.url}/liek/note/${param.id}", id = "${applicationConfig.url}/liek/note/${param.id}",
content = param.reaction content = param.reaction
), ),

View File

@ -32,12 +32,12 @@ class APUndoProcessor(
"Follow" -> { "Follow" -> {
val follow = undo.`object` as Follow val follow = undo.`object` as Follow
if (follow.`object` == null) { if (follow.apObject == null) {
return return
} }
apUserService.fetchPerson(undo.actor, follow.`object`) apUserService.fetchPerson(undo.actor, follow.apObject)
val follower = userQueryService.findByUrl(undo.actor) val follower = userQueryService.findByUrl(undo.actor)
val target = userQueryService.findByUrl(follow.`object`) val target = userQueryService.findByUrl(follow.apObject)
userService.unfollow(target.id, follower.id) userService.unfollow(target.id, follower.id)
return return
} }

View File

@ -24,7 +24,7 @@ class APSendFollowServiceImplTest {
apSendFollowServiceImpl.sendFollow(sendFollowDto) apSendFollowServiceImpl.sendFollow(sendFollowDto)
val value = Follow( val value = Follow(
`object` = sendFollowDto.followTargetUserId.url, apObject = sendFollowDto.followTargetUserId.url,
actor = sendFollowDto.userId.url actor = sendFollowDto.userId.url
) )
verify(apRequestService, times(1)).apPost( verify(apRequestService, times(1)).apPost(

View File

@ -47,7 +47,7 @@ class APRequestServiceImplTest {
) )
val responseClass = Follow( val responseClass = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apGet("https://example.com", responseClass = responseClass::class.java) apRequestServiceImpl.apGet("https://example.com", responseClass = responseClass::class.java)
@ -72,7 +72,7 @@ class APRequestServiceImplTest {
) )
val responseClass = Follow( val responseClass = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apGet( apRequestServiceImpl.apGet(
@ -112,7 +112,7 @@ class APRequestServiceImplTest {
) )
val responseClass = Follow( val responseClass = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apGet( apRequestServiceImpl.apGet(
@ -163,7 +163,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost("https://example.com", body, null) apRequestServiceImpl.apPost("https://example.com", body, null)
@ -209,7 +209,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost("https://example.com", body, null) apRequestServiceImpl.apPost("https://example.com", body, null)
@ -239,7 +239,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost("https://example.com", body, UserBuilder.remoteUserOf()) apRequestServiceImpl.apPost("https://example.com", body, UserBuilder.remoteUserOf())
@ -280,7 +280,7 @@ class APRequestServiceImplTest {
}), objectMapper, httpSignatureSigner, dateTimeFormatter) }), objectMapper, httpSignatureSigner, dateTimeFormatter)
val body = Follow( val body = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
apRequestServiceImpl.apPost( apRequestServiceImpl.apPost(
@ -330,7 +330,7 @@ class APRequestServiceImplTest {
}), objectMapper, mock(), dateTimeFormatter) }), objectMapper, mock(), dateTimeFormatter)
val body = Follow( val body = Follow(
`object` = "https://example.com", apObject = "https://example.com",
actor = "https://example.com" actor = "https://example.com"
) )
val actual = apRequestServiceImpl.apPost("https://example.com", body, null, body::class.java) val actual = apRequestServiceImpl.apPost("https://example.com", body, null, body::class.java)

View File

@ -12,8 +12,8 @@ class ContextSerializerTest {
val accept = Accept( val accept = Accept(
name = "aaa", name = "aaa",
actor = "bbb", actor = "bbb",
`object` = Follow( apObject = Follow(
`object` = "ddd", apObject = "ddd",
actor = "aaa" actor = "aaa"
) )
) )