feat: 新規ユーザー作成時にInstanceを取得するように

This commit is contained in:
usbharu 2023-11-18 11:37:51 +09:00
parent bb87cab45f
commit 4837192139
4 changed files with 72 additions and 2 deletions

View File

@ -1,17 +1,64 @@
package dev.usbharu.hideout.core.service.instance package dev.usbharu.hideout.core.service.instance
import com.fasterxml.jackson.databind.ObjectMapper
import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo
import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo2_0
import dev.usbharu.hideout.core.domain.model.instance.Instance 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.InstanceRepository
import dev.usbharu.hideout.core.service.resource.ResourceResolveService
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.net.URL
import java.time.Instant import java.time.Instant
interface InstanceService { interface InstanceService {
suspend fun fetchInstance(url: String): Instance
suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance
} }
@Service @Service
class InstanceServiceImpl(private val instanceRepository: InstanceRepository) : InstanceService { class InstanceServiceImpl(
private val instanceRepository: InstanceRepository,
private val resourceResolveService: ResourceResolveService,
private val objectMapper: ObjectMapper
) : InstanceService {
override suspend fun fetchInstance(url: String): Instance {
val u = URL(url)
val resolveInstanceUrl = u.protocol + "://" + u.host
val nodeinfoJson = resourceResolveService.resolve("$resolveInstanceUrl/.well-known/nodeinfo").bodyAsText()
val nodeinfo = objectMapper.readValue(nodeinfoJson, Nodeinfo::class.java)
val nodeinfoPathMap = nodeinfo.links.map { it.rel to it.href }.toMap()
for ((key, value) in nodeinfoPathMap) {
when (key) {
"http://nodeinfo.diaspora.software/ns/schema/2.0" -> {
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",
null,
nodeinfo20.software.name,
nodeinfo20.software.version
)
return createNewInstance(instanceCreateDto)
}
else -> {
TODO()
}
}
}
throw IllegalStateException("Nodeinfo aren't found.")
}
override suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance { override suspend fun createNewInstance(instanceCreateDto: InstanceCreateDto): Instance {
val instance = Instance( val instance = Instance(
instanceRepository.generateId(), instanceRepository.generateId(),

View File

@ -7,7 +7,24 @@ import java.io.InputStream
class KtorResolveResponse(val ktorHttpResponse: HttpResponse) : ResolveResponse { class KtorResolveResponse(val ktorHttpResponse: HttpResponse) : ResolveResponse {
private lateinit var _bodyAsText: String
private lateinit var _bodyAsBytes: ByteArray
override suspend fun body(): InputStream = ktorHttpResponse.bodyAsChannel().toInputStream() override suspend fun body(): InputStream = ktorHttpResponse.bodyAsChannel().toInputStream()
override suspend fun bodyAsText(): String {
if (!this::_bodyAsText.isInitialized) {
_bodyAsText = ktorHttpResponse.bodyAsText()
}
return _bodyAsText
}
override suspend fun bodyAsBytes(): ByteArray {
if (!this::_bodyAsBytes.isInitialized) {
_bodyAsBytes = ktorHttpResponse.readBytes()
}
return _bodyAsBytes
}
override suspend fun header(): Map<String, List<String>> = ktorHttpResponse.headers.toMap() override suspend fun header(): Map<String, List<String>> = ktorHttpResponse.headers.toMap()
override suspend fun status(): Int = ktorHttpResponse.status.value override suspend fun status(): Int = ktorHttpResponse.status.value
override suspend fun statusMessage(): String = ktorHttpResponse.status.description override suspend fun statusMessage(): String = ktorHttpResponse.status.description

View File

@ -4,6 +4,8 @@ import java.io.InputStream
interface ResolveResponse { interface ResolveResponse {
suspend fun body(): InputStream suspend fun body(): InputStream
suspend fun bodyAsText(): String
suspend fun bodyAsBytes(): ByteArray
suspend fun header(): Map<String, List<String>> suspend fun header(): Map<String, List<String>>
suspend fun status(): Int suspend fun status(): Int
suspend fun statusMessage(): String suspend fun statusMessage(): String

View File

@ -8,6 +8,7 @@ import dev.usbharu.hideout.core.domain.model.user.UserRepository
import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.FollowerQueryService
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.follow.SendFollowDto import dev.usbharu.hideout.core.service.follow.SendFollowDto
import dev.usbharu.hideout.core.service.instance.InstanceService
import org.jetbrains.exposed.exceptions.ExposedSQLException import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.time.Instant import java.time.Instant
@ -20,7 +21,8 @@ class UserServiceImpl(
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService, private val followerQueryService: FollowerQueryService,
private val userBuilder: User.UserBuilder, private val userBuilder: User.UserBuilder,
private val applicationConfig: ApplicationConfig private val applicationConfig: ApplicationConfig,
private val instanceService: InstanceService
) : ) :
UserService { UserService {
@ -55,6 +57,8 @@ class UserServiceImpl(
} }
override suspend fun createRemoteUser(user: RemoteUserCreateDto): User { override suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
instanceService.fetchInstance(user.url)
val nextId = userRepository.nextId() val nextId = userRepository.nextId()
val userEntity = userBuilder.of( val userEntity = userBuilder.of(
id = nextId, id = nextId,