From 5846dde42f03aaffdbbe8819f402acc533078470 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Mon, 10 Apr 2023 16:49:11 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=86=E3=83=BC=E3=83=96=E3=83=AB=E3=81=AB=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E6=83=85=E5=A0=B1=E3=82=92=E8=A8=98=E9=8C=B2?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/dev/usbharu/hideout/Application.kt | 2 +- src/main/kotlin/dev/usbharu/hideout/ap/Key.kt | 6 ++-- .../kotlin/dev/usbharu/hideout/ap/Person.kt | 4 +-- .../ap/IllegalActivityPubObjectException.kt | 8 +++++ .../hideout/repository/IUserRepository.kt | 6 ++++ .../hideout/repository/UserRepository.kt | 22 ++++++++++++ .../hideout/service/IUserAuthService.kt | 12 ++++--- .../ActivityPubFollowServiceImpl.kt | 11 ++++-- .../activitypub/ActivityPubUserServiceImpl.kt | 34 +++++++++++++++++-- .../hideout/service/impl/UserAuthService.kt | 5 +++ .../hideout/service/impl/UserService.kt | 12 +++++++ .../hideout/plugins/ActivityPubKtTest.kt | 12 +++++++ .../usbharu/hideout/plugins/KtorKeyMapTest.kt | 12 +++++++ 13 files changed, 130 insertions(+), 16 deletions(-) create mode 100644 src/main/kotlin/dev/usbharu/hideout/exception/ap/IllegalActivityPubObjectException.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt index 66b0b169..320ec162 100644 --- a/src/main/kotlin/dev/usbharu/hideout/Application.kt +++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt @@ -81,7 +81,7 @@ fun Application.parent() { } } } - single { ActivityPubFollowServiceImpl(get(), get(), get()) } + single { ActivityPubFollowServiceImpl(get(), get(), get(),get()) } single { ActivityPubServiceImpl(get()) } single { UserService(get()) } single { ActivityPubUserServiceImpl(get(), get(), get()) } diff --git a/src/main/kotlin/dev/usbharu/hideout/ap/Key.kt b/src/main/kotlin/dev/usbharu/hideout/ap/Key.kt index ab3ae13b..b3dccdfd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/ap/Key.kt +++ b/src/main/kotlin/dev/usbharu/hideout/ap/Key.kt @@ -1,9 +1,9 @@ package dev.usbharu.hideout.ap open class Key : Object{ - private var id:String? = null - private var owner:String? = null - private var publicKeyPem:String? = null + var id:String? = null + var owner:String? = null + var publicKeyPem:String? = null protected constructor() : super() constructor( type: List, diff --git a/src/main/kotlin/dev/usbharu/hideout/ap/Person.kt b/src/main/kotlin/dev/usbharu/hideout/ap/Person.kt index 270eba23..148892b0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/ap/Person.kt +++ b/src/main/kotlin/dev/usbharu/hideout/ap/Person.kt @@ -5,10 +5,10 @@ open class Person : Object { var preferredUsername:String? = null var summary:String? = null var inbox:String? = null - private var outbox:String? = null + var outbox:String? = null private var url:String? = null private var icon:Image? = null - private var publicKey:Key? = null + var publicKey:Key? = null protected constructor() : super() constructor( type: List = emptyList(), diff --git a/src/main/kotlin/dev/usbharu/hideout/exception/ap/IllegalActivityPubObjectException.kt b/src/main/kotlin/dev/usbharu/hideout/exception/ap/IllegalActivityPubObjectException.kt new file mode 100644 index 00000000..12965d62 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/exception/ap/IllegalActivityPubObjectException.kt @@ -0,0 +1,8 @@ +package dev.usbharu.hideout.exception.ap + +class IllegalActivityPubObjectException : IllegalArgumentException { + constructor() : super() + constructor(s: String?) : super(s) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) +} diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt index 53001878..dd89dbd9 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt @@ -8,10 +8,16 @@ interface IUserRepository { suspend fun findById(id: Long): UserEntity? + suspend fun findByIds(ids: List): List + suspend fun findByName(name: String): UserEntity? + suspend fun findByNameAndDomains(names: List>): List + suspend fun findByUrl(url:String):UserEntity? + suspend fun findByUrls(urls: List): List + suspend fun update(userEntity: UserEntity) suspend fun delete(id: Long) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt index 6a262e2b..2bb4abe5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt @@ -79,6 +79,14 @@ class UserRepository(private val database: Database) : IUserRepository { } } + override suspend fun findByIds(ids: List): List { + return query { + Users.select { Users.id inList ids }.map { + it.toUserEntity() + } + } + } + override suspend fun findByName(name: String): UserEntity? { return query { Users.select { Users.name eq name }.map { @@ -87,12 +95,26 @@ class UserRepository(private val database: Database) : IUserRepository { } } + override suspend fun findByNameAndDomains(names: List>): List { + return query { + val selectAll = Users.selectAll() + names.forEach { (name, domain) -> + selectAll.orWhere { Users.name eq name and (Users.domain eq domain) } + } + selectAll.map { it.toUserEntity() } + } + } + override suspend fun findByUrl(url: String): UserEntity? { return query { Users.select { Users.url eq url }.singleOrNull()?.toUserEntity() } } + override suspend fun findByUrls(urls: List): List { + TODO("Not yet implemented") + } + override suspend fun findFollowersById(id: Long): List { return query { val followers = Users.alias("FOLLOWERS") diff --git a/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt index e949d4d4..d2096d37 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt @@ -1,16 +1,18 @@ package dev.usbharu.hideout.service +import dev.usbharu.hideout.domain.model.UserAuthentication import dev.usbharu.hideout.domain.model.UserAuthenticationEntity interface IUserAuthService { - fun hash(password:String): String + fun hash(password: String): String - suspend fun usernameAlreadyUse(username: String):Boolean + suspend fun usernameAlreadyUse(username: String): Boolean suspend fun registerAccount(username: String, hash: String) - suspend fun verifyAccount(username: String,password: String): Boolean + suspend fun verifyAccount(username: String, password: String): Boolean - suspend fun findByUserId(userId: Long):UserAuthenticationEntity + suspend fun findByUserId(userId: Long): UserAuthenticationEntity - suspend fun findByUsername(username: String):UserAuthenticationEntity + suspend fun findByUsername(username: String): UserAuthenticationEntity + suspend fun createAccount(userEntity: UserAuthentication): UserAuthenticationEntity } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt index 925a735c..0a606f4a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt @@ -8,6 +8,7 @@ import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ActivityPubStringResponse import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob import dev.usbharu.hideout.plugins.postAp +import dev.usbharu.hideout.service.impl.UserService import dev.usbharu.hideout.service.job.JobQueueParentService import io.ktor.client.* import io.ktor.http.* @@ -16,6 +17,7 @@ import kjob.core.job.JobProps class ActivityPubFollowServiceImpl( private val jobQueueParentService: JobQueueParentService, private val activityPubUserService: ActivityPubUserService, + private val userService: UserService, private val httpClient: HttpClient ) : ActivityPubFollowService { override suspend fun receiveFollow(follow: Follow): ActivityPubResponse { @@ -32,14 +34,19 @@ class ActivityPubFollowServiceImpl( val actor = props[ReceiveFollowJob.actor] val person = activityPubUserService.fetchPerson(actor) val follow = Config.configData.objectMapper.readValue(props[ReceiveFollowJob.follow]) + val targetActor = props[ReceiveFollowJob.targetActor] httpClient.postAp( urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"), - username = "${props[ReceiveFollowJob.targetActor]}#pubkey", + username = "$targetActor#pubkey", jsonLd = Accept( name = "Follow", `object` = follow, - actor = props[ReceiveFollowJob.targetActor] + actor = targetActor ) ) + val users = + userService.findByUrls(listOf(targetActor, follow.actor ?: throw IllegalArgumentException("actor is null"))) + + userService.addFollowers(users.first { it.url == targetActor }.id, users.first { it.url == follow.actor }.id) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt index 4af88bac..2c5c5002 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt @@ -5,7 +5,10 @@ import dev.usbharu.hideout.ap.Image import dev.usbharu.hideout.ap.Key import dev.usbharu.hideout.ap.Person import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.User +import dev.usbharu.hideout.domain.model.UserAuthentication import dev.usbharu.hideout.exception.UserNotFoundException +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException import dev.usbharu.hideout.service.IUserAuthService import dev.usbharu.hideout.service.impl.UserService import dev.usbharu.hideout.util.HttpUtil.Activity @@ -14,7 +17,11 @@ import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* -class ActivityPubUserServiceImpl(private val userService: UserService, private val userAuthService: IUserAuthService,private val httpClient: HttpClient) : +class ActivityPubUserServiceImpl( + private val userService: UserService, + private val userAuthService: IUserAuthService, + private val httpClient: HttpClient +) : ActivityPubUserService { override suspend fun getPersonByName(name: String): Person { // TODO: JOINで書き直し @@ -74,11 +81,32 @@ class ActivityPubUserServiceImpl(private val userService: UserService, private v ) ) - } catch (e:UserNotFoundException){ + } catch (e: UserNotFoundException) { val httpResponse = httpClient.get(url) { accept(ContentType.Application.Activity) } - Config.configData.objectMapper.readValue(httpResponse.bodyAsText()) + val person = Config.configData.objectMapper.readValue(httpResponse.bodyAsText()) + val userEntity = userService.create( + User( + name = person.preferredUsername + ?: throw IllegalActivityPubObjectException("preferredUsername is null"), + domain = url.substringAfter(":").substringBeforeLast("/"), + screenName = person.name ?: throw IllegalActivityPubObjectException("name is null"), + description = person.summary ?: throw IllegalActivityPubObjectException("summary is null"), + inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"), + outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"), + url = url + ) + ) + userAuthService.createAccount( + UserAuthentication( + userEntity.id, + null, + person.publicKey?.publicKeyPem ?: throw IllegalActivityPubObjectException("publicKey is null"), + null + ) + ) + person } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt index 88247524..5542d1ee 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt @@ -4,6 +4,7 @@ import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.User import dev.usbharu.hideout.domain.model.UserAuthentication import dev.usbharu.hideout.domain.model.UserAuthenticationEntity +import dev.usbharu.hideout.domain.model.UserEntity import dev.usbharu.hideout.exception.UserNotFoundException import dev.usbharu.hideout.repository.IUserAuthRepository import dev.usbharu.hideout.repository.IUserRepository @@ -76,6 +77,10 @@ class UserAuthService( ?: throw UserNotFoundException("$username auth data was not found") } + override suspend fun createAccount(userEntity: UserAuthentication): UserAuthenticationEntity { + return userAuthRepository.create(userEntity) + } + private fun generateKeyPair(): KeyPair { val keyPairGenerator = KeyPairGenerator.getInstance("RSA") keyPairGenerator.initialize(1024) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt index f090d38f..a64ccd04 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt @@ -21,15 +21,27 @@ class UserService(private val userRepository: IUserRepository) { return userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.") } + suspend fun findByIds(ids: List): List { + return userRepository.findByIds(ids) + } + suspend fun findByName(name: String): UserEntity { return userRepository.findByName(name) ?: throw UserNotFoundException("$name was not found.") } + suspend fun findByNameAndDomains(names: List>): List { + return userRepository.findByNameAndDomains(names) + } + suspend fun findByUrl(url: String): UserEntity { return userRepository.findByUrl(url) ?: throw UserNotFoundException("$url was not found.") } + suspend fun findByUrls(urls: List): List { + return userRepository.findByUrls(urls) + } + suspend fun create(user: User): UserEntity { return userRepository.create(user) } diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt index 8cadb063..19246b90 100644 --- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt @@ -31,14 +31,26 @@ class ActivityPubKtTest { TODO("Not yet implemented") } + override suspend fun findByIds(ids: List): List { + TODO("Not yet implemented") + } + override suspend fun findByName(name: String): UserEntity? { return UserEntity(1, "test", "localhost", "test", "","","","") } + override suspend fun findByNameAndDomains(names: List>): List { + TODO("Not yet implemented") + } + override suspend fun findByUrl(url: String): UserEntity? { TODO("Not yet implemented") } + override suspend fun findByUrls(urls: List): List { + TODO("Not yet implemented") + } + override suspend fun update(userEntity: UserEntity) { TODO("Not yet implemented") } diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt index 7e87a802..02cfb9b4 100644 --- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt @@ -26,14 +26,26 @@ class KtorKeyMapTest { TODO("Not yet implemented") } + override suspend fun findByIds(ids: List): List { + TODO("Not yet implemented") + } + override suspend fun findByName(name: String): UserEntity? { return UserEntity(1, "test", "localhost", "test", "","","","") } + override suspend fun findByNameAndDomains(names: List>): List { + TODO("Not yet implemented") + } + override suspend fun findByUrl(url: String): UserEntity? { TODO("Not yet implemented") } + override suspend fun findByUrls(urls: List): List { + TODO("Not yet implemented") + } + override suspend fun update(userEntity: UserEntity) { TODO("Not yet implemented") }