mirror of https://github.com/usbharu/Hideout.git
feat: フォローテーブルにフォロー情報を記録するように
This commit is contained in:
parent
a9200eaeef
commit
5846dde42f
|
@ -81,7 +81,7 @@ fun Application.parent() {
|
|||
}
|
||||
}
|
||||
}
|
||||
single<ActivityPubFollowService> { ActivityPubFollowServiceImpl(get(), get(), get()) }
|
||||
single<ActivityPubFollowService> { ActivityPubFollowServiceImpl(get(), get(), get(),get()) }
|
||||
single<ActivityPubService> { ActivityPubServiceImpl(get()) }
|
||||
single<UserService> { UserService(get()) }
|
||||
single<ActivityPubUserService> { ActivityPubUserServiceImpl(get(), get(), get()) }
|
||||
|
|
|
@ -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<String>,
|
||||
|
|
|
@ -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<String> = emptyList(),
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -8,10 +8,16 @@ interface IUserRepository {
|
|||
|
||||
suspend fun findById(id: Long): UserEntity?
|
||||
|
||||
suspend fun findByIds(ids: List<Long>): List<UserEntity>
|
||||
|
||||
suspend fun findByName(name: String): UserEntity?
|
||||
|
||||
suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<UserEntity>
|
||||
|
||||
suspend fun findByUrl(url:String):UserEntity?
|
||||
|
||||
suspend fun findByUrls(urls: List<String>): List<UserEntity>
|
||||
|
||||
suspend fun update(userEntity: UserEntity)
|
||||
|
||||
suspend fun delete(id: Long)
|
||||
|
|
|
@ -79,6 +79,14 @@ class UserRepository(private val database: Database) : IUserRepository {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun findByIds(ids: List<Long>): List<UserEntity> {
|
||||
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<Pair<String, String>>): List<UserEntity> {
|
||||
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<String>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findFollowersById(id: Long): List<UserEntity> {
|
||||
return query {
|
||||
val followers = Users.alias("FOLLOWERS")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package dev.usbharu.hideout.service
|
||||
|
||||
import dev.usbharu.hideout.domain.model.UserAuthentication
|
||||
import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
|
||||
|
||||
interface IUserAuthService {
|
||||
|
@ -13,4 +14,5 @@ interface IUserAuthService {
|
|||
suspend fun findByUserId(userId: Long): UserAuthenticationEntity
|
||||
|
||||
suspend fun findByUsername(username: String): UserAuthenticationEntity
|
||||
suspend fun createAccount(userEntity: UserAuthentication): UserAuthenticationEntity
|
||||
}
|
||||
|
|
|
@ -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<Follow>(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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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で書き直し
|
||||
|
@ -78,7 +85,28 @@ class ActivityPubUserServiceImpl(private val userService: UserService, private v
|
|||
val httpResponse = httpClient.get(url) {
|
||||
accept(ContentType.Application.Activity)
|
||||
}
|
||||
Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText())
|
||||
val person = Config.configData.objectMapper.readValue<Person>(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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<Long>): List<UserEntity> {
|
||||
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<Pair<String,String>>): List<UserEntity> {
|
||||
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<String>): List<UserEntity> {
|
||||
return userRepository.findByUrls(urls)
|
||||
}
|
||||
|
||||
suspend fun create(user: User): UserEntity {
|
||||
return userRepository.create(user)
|
||||
}
|
||||
|
|
|
@ -31,14 +31,26 @@ class ActivityPubKtTest {
|
|||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByIds(ids: List<Long>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByName(name: String): UserEntity? {
|
||||
return UserEntity(1, "test", "localhost", "test", "","","","")
|
||||
}
|
||||
|
||||
override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByUrl(url: String): UserEntity? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByUrls(urls: List<String>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun update(userEntity: UserEntity) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
|
|
@ -26,14 +26,26 @@ class KtorKeyMapTest {
|
|||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByIds(ids: List<Long>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByName(name: String): UserEntity? {
|
||||
return UserEntity(1, "test", "localhost", "test", "","","","")
|
||||
}
|
||||
|
||||
override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByUrl(url: String): UserEntity? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByUrls(urls: List<String>): List<UserEntity> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun update(userEntity: UserEntity) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue