feat: Instanceの重複チェックを追加

This commit is contained in:
usbharu 2023-11-18 12:20:29 +09:00
parent ee56adcf27
commit 9cc8c77cbd
7 changed files with 94 additions and 12 deletions

View File

@ -124,7 +124,8 @@ class APUserServiceImpl(
?: throw IllegalActivityPubObjectException("publicKey is null"),
keyId = person.publicKey?.id ?: throw IllegalActivityPubObjectException("publicKey keyId is null"),
following = person.following,
followers = person.followers
followers = person.followers,
sharedInbox = person.endpoints["sharedInbox"]
)
)
}

View File

@ -0,0 +1,22 @@
package dev.usbharu.hideout.core.domain.model.instance
class Nodeinfo2_0 {
var metadata: Metadata? = null
var software: Software? = null
protected constructor()
}
class Metadata {
var nodeName: String? = null
var nodeDescription: String? = null
protected constructor()
}
class Software {
var name: String? = null
var version: String? = null
protected constructor()
}

View File

@ -0,0 +1,16 @@
package dev.usbharu.hideout.core.infrastructure.exposedquery
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Instance
import dev.usbharu.hideout.core.infrastructure.exposedrepository.toInstance
import dev.usbharu.hideout.core.query.InstanceQueryService
import dev.usbharu.hideout.util.singleOr
import org.jetbrains.exposed.sql.select
import org.springframework.stereotype.Repository
import dev.usbharu.hideout.core.domain.model.instance.Instance as InstanceEntity
@Repository
class InstanceQueryServiceImpl : InstanceQueryService {
override suspend fun findByUrl(url: String): InstanceEntity = Instance.select { Instance.url eq url }
.singleOr { FailedToGetResourcesException("url is doesn't exist") }.toInstance()
}

View File

@ -0,0 +1,7 @@
package dev.usbharu.hideout.core.query
import dev.usbharu.hideout.core.domain.model.instance.Instance
interface InstanceQueryService {
suspend fun findByUrl(url: String): Instance
}

View File

@ -1,18 +1,21 @@
package dev.usbharu.hideout.core.service.instance
import com.fasterxml.jackson.databind.ObjectMapper
import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo2_0
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
import dev.usbharu.hideout.core.domain.model.instance.Instance
import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository
import dev.usbharu.hideout.core.domain.model.instance.Nodeinfo
import dev.usbharu.hideout.core.domain.model.instance.Nodeinfo2_0
import dev.usbharu.hideout.core.query.InstanceQueryService
import dev.usbharu.hideout.core.service.resource.ResourceResolveService
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import java.net.URL
import java.time.Instant
interface InstanceService {
suspend fun fetchInstance(url: String): Instance
suspend fun fetchInstance(url: String, sharedInbox: String? = null): Instance
suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance
}
@ -21,11 +24,20 @@ interface InstanceService {
class InstanceServiceImpl(
private val instanceRepository: InstanceRepository,
private val resourceResolveService: ResourceResolveService,
@Qualifier("activitypub") private val objectMapper: ObjectMapper
@Qualifier("activitypub") private val objectMapper: ObjectMapper,
private val instanceQueryService: InstanceQueryService
) : InstanceService {
override suspend fun fetchInstance(url: String): Instance {
override suspend fun fetchInstance(url: String, sharedInbox: String?): Instance {
val u = URL(url)
val resolveInstanceUrl = u.protocol + "://" + u.host
try {
return instanceQueryService.findByUrl(url)
} catch (e: FailedToGetResourcesException) {
logger.info("Instance not found. try fetch instance info. url: {}", resolveInstanceUrl)
logger.debug("Failed to get resources. url: {}", resolveInstanceUrl, e)
}
val nodeinfoJson = resourceResolveService.resolve("$resolveInstanceUrl/.well-known/nodeinfo").bodyAsText()
val nodeinfo = objectMapper.readValue(nodeinfoJson, Nodeinfo::class.java)
val nodeinfoPathMap = nodeinfo.links.associate { it.rel to it.href }
@ -40,13 +52,32 @@ class InstanceServiceImpl(
)
val instanceCreateDto = InstanceCreateDto(
nodeinfo20.metadata.nodeName,
nodeinfo20.metadata.nodeDescription,
nodeinfo20.metadata?.nodeName,
nodeinfo20.metadata?.nodeDescription,
resolveInstanceUrl,
resolveInstanceUrl + "/favicon.ico",
null,
nodeinfo20.software.name,
nodeinfo20.software.version
sharedInbox,
nodeinfo20.software?.name,
nodeinfo20.software?.version
)
return createNewInstance(instanceCreateDto)
}
// TODO: 多分2.0と2.1で互換性有るのでそのまま使うけどなおす
"http://nodeinfo.diaspora.software/ns/schema/2.1" -> {
val nodeinfo20 = objectMapper.readValue(
resourceResolveService.resolve(value!!).bodyAsText(),
Nodeinfo2_0::class.java
)
val instanceCreateDto = InstanceCreateDto(
nodeinfo20.metadata?.nodeName,
nodeinfo20.metadata?.nodeDescription,
resolveInstanceUrl,
resolveInstanceUrl + "/favicon.ico",
sharedInbox,
nodeinfo20.software?.name,
nodeinfo20.software?.version
)
return createNewInstance(instanceCreateDto)
}
@ -78,4 +109,8 @@ class InstanceServiceImpl(
instanceRepository.save(instance)
return instance
}
companion object {
private val logger = LoggerFactory.getLogger(InstanceServiceImpl::class.java)
}
}

View File

@ -11,5 +11,6 @@ data class RemoteUserCreateDto(
val publicKey: String,
val keyId: String,
val followers: String?,
val following: String?
val following: String?,
val sharedInbox: String?
)

View File

@ -57,7 +57,7 @@ class UserServiceImpl(
}
override suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
instanceService.fetchInstance(user.url)
instanceService.fetchInstance(user.url, user.sharedInbox)
val nextId = userRepository.nextId()
val userEntity = userBuilder.of(