mirror of https://github.com/usbharu/Hideout.git
Merge pull request #30 from usbharu/feature/refactor-filename
Feature/refactor filename
This commit is contained in:
commit
714ac201e5
|
@ -15,17 +15,17 @@ import dev.usbharu.hideout.plugins.*
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.routing.register
|
import dev.usbharu.hideout.routing.register
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubService
|
import dev.usbharu.hideout.service.ap.APService
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
import dev.usbharu.hideout.service.ap.APUserService
|
||||||
import dev.usbharu.hideout.service.api.IPostApiService
|
import dev.usbharu.hideout.service.api.PostApiService
|
||||||
import dev.usbharu.hideout.service.api.IUserApiService
|
import dev.usbharu.hideout.service.api.UserApiService
|
||||||
import dev.usbharu.hideout.service.api.UserAuthApiService
|
import dev.usbharu.hideout.service.api.UserAuthApiService
|
||||||
import dev.usbharu.hideout.service.api.WebFingerApiService
|
import dev.usbharu.hideout.service.api.WebFingerApiService
|
||||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
||||||
import dev.usbharu.hideout.service.core.*
|
import dev.usbharu.hideout.service.core.*
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import dev.usbharu.hideout.service.job.KJobJobQueueParentService
|
import dev.usbharu.hideout.service.job.KJobJobQueueParentService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import dev.usbharu.kjob.exposed.ExposedKJob
|
import dev.usbharu.kjob.exposed.ExposedKJob
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.engine.cio.*
|
import io.ktor.client.engine.cio.*
|
||||||
|
@ -94,26 +94,26 @@ fun Application.parent() {
|
||||||
configureKoin(module, HideoutModule().module)
|
configureKoin(module, HideoutModule().module)
|
||||||
configureStatusPages()
|
configureStatusPages()
|
||||||
runBlocking {
|
runBlocking {
|
||||||
inject<IServerInitialiseService>().value.init()
|
inject<ServerInitialiseService>().value.init()
|
||||||
}
|
}
|
||||||
configureCompression()
|
configureCompression()
|
||||||
configureHTTP()
|
configureHTTP()
|
||||||
configureStaticRouting()
|
configureStaticRouting()
|
||||||
configureMonitoring()
|
configureMonitoring()
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
register(inject<IUserApiService>().value)
|
register(inject<UserApiService>().value)
|
||||||
configureSecurity(
|
configureSecurity(
|
||||||
|
|
||||||
inject<JwkProvider>().value,
|
inject<JwkProvider>().value,
|
||||||
inject<IMetaService>().value
|
inject<MetaService>().value
|
||||||
)
|
)
|
||||||
configureRouting(
|
configureRouting(
|
||||||
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
|
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
|
||||||
activityPubService = inject<ActivityPubService>().value,
|
apService = inject<APService>().value,
|
||||||
userService = inject<IUserService>().value,
|
userService = inject<UserService>().value,
|
||||||
activityPubUserService = inject<ActivityPubUserService>().value,
|
apUserService = inject<APUserService>().value,
|
||||||
postService = inject<IPostApiService>().value,
|
postService = inject<PostApiService>().value,
|
||||||
userApiService = inject<IUserApiService>().value,
|
userApiService = inject<UserApiService>().value,
|
||||||
userQueryService = inject<UserQueryService>().value,
|
userQueryService = inject<UserQueryService>().value,
|
||||||
followerQueryService = inject<FollowerQueryService>().value,
|
followerQueryService = inject<FollowerQueryService>().value,
|
||||||
userAuthApiService = inject<UserAuthApiService>().value,
|
userAuthApiService = inject<UserAuthApiService>().value,
|
||||||
|
@ -128,28 +128,28 @@ fun Application.worker() {
|
||||||
connectionDatabase = inject<Database>().value
|
connectionDatabase = inject<Database>().value
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
val activityPubService = inject<ActivityPubService>().value
|
val apService = inject<APService>().value
|
||||||
|
|
||||||
kJob.register(ReceiveFollowJob) {
|
kJob.register(ReceiveFollowJob) {
|
||||||
execute {
|
execute {
|
||||||
activityPubService.processActivity(this, it)
|
apService.processActivity(this, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kJob.register(DeliverPostJob) {
|
kJob.register(DeliverPostJob) {
|
||||||
execute {
|
execute {
|
||||||
activityPubService.processActivity(this, it)
|
apService.processActivity(this, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kJob.register(DeliverReactionJob) {
|
kJob.register(DeliverReactionJob) {
|
||||||
execute {
|
execute {
|
||||||
activityPubService.processActivity(this, it)
|
apService.processActivity(this, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kJob.register(DeliverRemoveReactionJob) {
|
kJob.register(DeliverRemoveReactionJob) {
|
||||||
execute {
|
execute {
|
||||||
activityPubService.processActivity(this, it)
|
apService.processActivity(this, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import dev.usbharu.hideout.service.activitypub.ExtendedActivityVocabulary
|
import dev.usbharu.hideout.service.ap.ExtendedActivityVocabulary
|
||||||
|
|
||||||
class ObjectDeserializer : JsonDeserializer<Object>() {
|
class ObjectDeserializer : JsonDeserializer<Object>() {
|
||||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||||
|
|
|
@ -4,7 +4,7 @@ import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.domain.model.ap.JsonLd
|
import dev.usbharu.hideout.domain.model.ap.JsonLd
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.UserAuthService
|
import dev.usbharu.hideout.service.user.UserAuthServiceImpl
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
import dev.usbharu.hideout.util.HttpUtil.Activity
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.plugins.api.*
|
import io.ktor.client.plugins.api.*
|
||||||
|
@ -73,7 +73,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
|
||||||
println("Digest !!")
|
println("Digest !!")
|
||||||
// UserAuthService.sha256.reset()
|
// UserAuthService.sha256.reset()
|
||||||
val digest =
|
val digest =
|
||||||
Base64.getEncoder().encodeToString(UserAuthService.sha256.digest(body.toByteArray(Charsets.UTF_8)))
|
Base64.getEncoder().encodeToString(UserAuthServiceImpl.sha256.digest(body.toByteArray(Charsets.UTF_8)))
|
||||||
request.headers.append("Digest", "sha-256=$digest")
|
request.headers.append("Digest", "sha-256=$digest")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,15 +9,15 @@ import dev.usbharu.hideout.routing.api.internal.v1.auth
|
||||||
import dev.usbharu.hideout.routing.api.internal.v1.posts
|
import dev.usbharu.hideout.routing.api.internal.v1.posts
|
||||||
import dev.usbharu.hideout.routing.api.internal.v1.users
|
import dev.usbharu.hideout.routing.api.internal.v1.users
|
||||||
import dev.usbharu.hideout.routing.wellknown.webfinger
|
import dev.usbharu.hideout.routing.wellknown.webfinger
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubService
|
import dev.usbharu.hideout.service.ap.APService
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
import dev.usbharu.hideout.service.ap.APUserService
|
||||||
import dev.usbharu.hideout.service.api.IPostApiService
|
import dev.usbharu.hideout.service.api.PostApiService
|
||||||
import dev.usbharu.hideout.service.api.IUserApiService
|
import dev.usbharu.hideout.service.api.UserApiService
|
||||||
import dev.usbharu.hideout.service.api.UserAuthApiService
|
import dev.usbharu.hideout.service.api.UserAuthApiService
|
||||||
import dev.usbharu.hideout.service.api.WebFingerApiService
|
import dev.usbharu.hideout.service.api.WebFingerApiService
|
||||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.server.plugins.autohead.*
|
import io.ktor.server.plugins.autohead.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
@ -25,11 +25,11 @@ import io.ktor.server.routing.*
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
fun Application.configureRouting(
|
fun Application.configureRouting(
|
||||||
httpSignatureVerifyService: HttpSignatureVerifyService,
|
httpSignatureVerifyService: HttpSignatureVerifyService,
|
||||||
activityPubService: ActivityPubService,
|
apService: APService,
|
||||||
userService: IUserService,
|
userService: UserService,
|
||||||
activityPubUserService: ActivityPubUserService,
|
apUserService: APUserService,
|
||||||
postService: IPostApiService,
|
postService: PostApiService,
|
||||||
userApiService: IUserApiService,
|
userApiService: UserApiService,
|
||||||
userQueryService: UserQueryService,
|
userQueryService: UserQueryService,
|
||||||
followerQueryService: FollowerQueryService,
|
followerQueryService: FollowerQueryService,
|
||||||
userAuthApiService: UserAuthApiService,
|
userAuthApiService: UserAuthApiService,
|
||||||
|
@ -38,9 +38,9 @@ fun Application.configureRouting(
|
||||||
) {
|
) {
|
||||||
install(AutoHeadResponse)
|
install(AutoHeadResponse)
|
||||||
routing {
|
routing {
|
||||||
inbox(httpSignatureVerifyService, activityPubService)
|
inbox(httpSignatureVerifyService, apService)
|
||||||
outbox()
|
outbox()
|
||||||
usersAP(activityPubUserService, userQueryService, followerQueryService, transaction)
|
usersAP(apUserService, userQueryService, followerQueryService, transaction)
|
||||||
webfinger(webFingerApiService)
|
webfinger(webFingerApiService)
|
||||||
route("/api/internal/v1") {
|
route("/api/internal/v1") {
|
||||||
posts(postService)
|
posts(postService)
|
||||||
|
|
|
@ -2,7 +2,7 @@ package dev.usbharu.hideout.plugins
|
||||||
|
|
||||||
import com.auth0.jwk.JwkProvider
|
import com.auth0.jwk.JwkProvider
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.service.core.IMetaService
|
import dev.usbharu.hideout.service.core.MetaService
|
||||||
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
|
@ -16,7 +16,7 @@ const val TOKEN_AUTH = "jwt-auth"
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
fun Application.configureSecurity(
|
fun Application.configureSecurity(
|
||||||
jwkProvider: JwkProvider,
|
jwkProvider: JwkProvider,
|
||||||
metaService: IMetaService
|
metaService: MetaService
|
||||||
) {
|
) {
|
||||||
val issuer = Config.configData.url
|
val issuer = Config.configData.url
|
||||||
install(Authentication) {
|
install(Authentication) {
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package dev.usbharu.hideout.repository
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
|
||||||
interface IUserRepository {
|
|
||||||
suspend fun save(user: User): User
|
|
||||||
|
|
||||||
suspend fun findById(id: Long): User?
|
|
||||||
|
|
||||||
suspend fun delete(id: Long)
|
|
||||||
|
|
||||||
suspend fun deleteFollowRequest(id: Long, follower: Long)
|
|
||||||
|
|
||||||
suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean
|
|
||||||
|
|
||||||
suspend fun nextId(): Long
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@ package dev.usbharu.hideout.repository
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
|
import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
|
||||||
|
|
||||||
interface IJwtRefreshTokenRepository {
|
interface JwtRefreshTokenRepository {
|
||||||
suspend fun generateId(): Long
|
suspend fun generateId(): Long
|
||||||
|
|
||||||
suspend fun save(token: JwtRefreshToken)
|
suspend fun save(token: JwtRefreshToken)
|
|
@ -13,7 +13,7 @@ class JwtRefreshTokenRepositoryImpl(
|
||||||
private val database: Database,
|
private val database: Database,
|
||||||
private val idGenerateService: IdGenerateService
|
private val idGenerateService: IdGenerateService
|
||||||
) :
|
) :
|
||||||
IJwtRefreshTokenRepository {
|
JwtRefreshTokenRepository {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
transaction(database) {
|
transaction(database) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package dev.usbharu.hideout.repository
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
||||||
|
|
||||||
interface IMetaRepository {
|
interface MetaRepository {
|
||||||
|
|
||||||
suspend fun save(meta: Meta)
|
suspend fun save(meta: Meta)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import org.koin.core.annotation.Single
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class MetaRepositoryImpl(private val database: Database) : IMetaRepository {
|
class MetaRepositoryImpl(private val database: Database) : MetaRepository {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
transaction(database) {
|
transaction(database) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package dev.usbharu.hideout.repository
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
interface IPostRepository {
|
interface PostRepository {
|
||||||
suspend fun generateId(): Long
|
suspend fun generateId(): Long
|
||||||
suspend fun save(post: Post): Post
|
suspend fun save(post: Post): Post
|
||||||
suspend fun delete(id: Long)
|
suspend fun delete(id: Long)
|
|
@ -9,7 +9,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : IPostRepository {
|
class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : PostRepository {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
transaction(database) {
|
transaction(database) {
|
||||||
|
|
|
@ -1,137 +1,18 @@
|
||||||
package dev.usbharu.hideout.repository
|
package dev.usbharu.hideout.repository
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import dev.usbharu.hideout.service.core.IdGenerateService
|
|
||||||
import org.jetbrains.exposed.dao.id.LongIdTable
|
|
||||||
import org.jetbrains.exposed.sql.*
|
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
@Single
|
@Suppress("TooManyFunctions")
|
||||||
class UserRepository(private val database: Database, private val idGenerateService: IdGenerateService) :
|
interface UserRepository {
|
||||||
IUserRepository {
|
suspend fun save(user: User): User
|
||||||
init {
|
|
||||||
transaction(database) {
|
|
||||||
SchemaUtils.create(Users)
|
|
||||||
SchemaUtils.create(UsersFollowers)
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(Users)
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(UsersFollowers)
|
|
||||||
SchemaUtils.create(FollowRequests)
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(FollowRequests)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun save(user: User): User {
|
suspend fun findById(id: Long): User?
|
||||||
val singleOrNull = Users.select { Users.id eq user.id }.singleOrNull()
|
|
||||||
if (singleOrNull == null) {
|
|
||||||
Users.insert {
|
|
||||||
it[id] = user.id
|
|
||||||
it[name] = user.name
|
|
||||||
it[domain] = user.domain
|
|
||||||
it[screenName] = user.screenName
|
|
||||||
it[description] = user.description
|
|
||||||
it[password] = user.password
|
|
||||||
it[inbox] = user.inbox
|
|
||||||
it[outbox] = user.outbox
|
|
||||||
it[url] = user.url
|
|
||||||
it[createdAt] = user.createdAt.toEpochMilli()
|
|
||||||
it[publicKey] = user.publicKey
|
|
||||||
it[privateKey] = user.privateKey
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Users.update({ Users.id eq user.id }) {
|
|
||||||
it[name] = user.name
|
|
||||||
it[domain] = user.domain
|
|
||||||
it[screenName] = user.screenName
|
|
||||||
it[description] = user.description
|
|
||||||
it[password] = user.password
|
|
||||||
it[inbox] = user.inbox
|
|
||||||
it[outbox] = user.outbox
|
|
||||||
it[url] = user.url
|
|
||||||
it[createdAt] = user.createdAt.toEpochMilli()
|
|
||||||
it[publicKey] = user.publicKey
|
|
||||||
it[privateKey] = user.privateKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun findById(id: Long): User? {
|
suspend fun delete(id: Long)
|
||||||
return Users.select { Users.id eq id }.map {
|
|
||||||
it.toUser()
|
|
||||||
}.singleOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun deleteFollowRequest(id: Long, follower: Long) {
|
suspend fun deleteFollowRequest(id: Long, follower: Long)
|
||||||
FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean {
|
suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean
|
||||||
return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) }
|
|
||||||
.singleOrNull() != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun delete(id: Long) {
|
suspend fun nextId(): Long
|
||||||
Users.deleteWhere { Users.id.eq(id) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun nextId(): Long = idGenerateService.generateId()
|
|
||||||
}
|
|
||||||
|
|
||||||
object Users : Table("users") {
|
|
||||||
val id = long("id")
|
|
||||||
val name = varchar("name", length = 64)
|
|
||||||
val domain = varchar("domain", length = 255)
|
|
||||||
val screenName = varchar("screen_name", length = 64)
|
|
||||||
val description = varchar("description", length = 600)
|
|
||||||
val password = varchar("password", length = 255).nullable()
|
|
||||||
val inbox = varchar("inbox", length = 255).uniqueIndex()
|
|
||||||
val outbox = varchar("outbox", length = 255).uniqueIndex()
|
|
||||||
val url = varchar("url", length = 255).uniqueIndex()
|
|
||||||
val publicKey = varchar("public_key", length = 10000)
|
|
||||||
val privateKey = varchar("private_key", length = 10000).nullable()
|
|
||||||
val createdAt = long("created_at")
|
|
||||||
|
|
||||||
override val primaryKey: PrimaryKey = PrimaryKey(id)
|
|
||||||
|
|
||||||
init {
|
|
||||||
uniqueIndex(name, domain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ResultRow.toUser(): User {
|
|
||||||
return User(
|
|
||||||
id = this[Users.id],
|
|
||||||
name = this[Users.name],
|
|
||||||
domain = this[Users.domain],
|
|
||||||
screenName = this[Users.screenName],
|
|
||||||
description = this[Users.description],
|
|
||||||
password = this[Users.password],
|
|
||||||
inbox = this[Users.inbox],
|
|
||||||
outbox = this[Users.outbox],
|
|
||||||
url = this[Users.url],
|
|
||||||
publicKey = this[Users.publicKey],
|
|
||||||
privateKey = this[Users.privateKey],
|
|
||||||
createdAt = Instant.ofEpochMilli((this[Users.createdAt]))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
object UsersFollowers : LongIdTable("users_followers") {
|
|
||||||
val userId = long("user_id").references(Users.id).index()
|
|
||||||
val followerId = long("follower_id").references(Users.id)
|
|
||||||
|
|
||||||
init {
|
|
||||||
uniqueIndex(userId, followerId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object FollowRequests : LongIdTable("follow_requests") {
|
|
||||||
val userId = long("user_id").references(Users.id)
|
|
||||||
val followerId = long("follower_id").references(Users.id)
|
|
||||||
|
|
||||||
init {
|
|
||||||
uniqueIndex(userId, followerId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
package dev.usbharu.hideout.repository
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
|
import dev.usbharu.hideout.service.core.IdGenerateService
|
||||||
|
import org.jetbrains.exposed.dao.id.LongIdTable
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class UserRepositoryImpl(private val database: Database, private val idGenerateService: IdGenerateService) :
|
||||||
|
UserRepository {
|
||||||
|
init {
|
||||||
|
transaction(database) {
|
||||||
|
SchemaUtils.create(Users)
|
||||||
|
SchemaUtils.create(UsersFollowers)
|
||||||
|
SchemaUtils.createMissingTablesAndColumns(Users)
|
||||||
|
SchemaUtils.createMissingTablesAndColumns(UsersFollowers)
|
||||||
|
SchemaUtils.create(FollowRequests)
|
||||||
|
SchemaUtils.createMissingTablesAndColumns(FollowRequests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun save(user: User): User {
|
||||||
|
val singleOrNull = Users.select { Users.id eq user.id }.singleOrNull()
|
||||||
|
if (singleOrNull == null) {
|
||||||
|
Users.insert {
|
||||||
|
it[id] = user.id
|
||||||
|
it[name] = user.name
|
||||||
|
it[domain] = user.domain
|
||||||
|
it[screenName] = user.screenName
|
||||||
|
it[description] = user.description
|
||||||
|
it[password] = user.password
|
||||||
|
it[inbox] = user.inbox
|
||||||
|
it[outbox] = user.outbox
|
||||||
|
it[url] = user.url
|
||||||
|
it[createdAt] = user.createdAt.toEpochMilli()
|
||||||
|
it[publicKey] = user.publicKey
|
||||||
|
it[privateKey] = user.privateKey
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Users.update({ Users.id eq user.id }) {
|
||||||
|
it[name] = user.name
|
||||||
|
it[domain] = user.domain
|
||||||
|
it[screenName] = user.screenName
|
||||||
|
it[description] = user.description
|
||||||
|
it[password] = user.password
|
||||||
|
it[inbox] = user.inbox
|
||||||
|
it[outbox] = user.outbox
|
||||||
|
it[url] = user.url
|
||||||
|
it[createdAt] = user.createdAt.toEpochMilli()
|
||||||
|
it[publicKey] = user.publicKey
|
||||||
|
it[privateKey] = user.privateKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun findById(id: Long): User? {
|
||||||
|
return Users.select { Users.id eq id }.map {
|
||||||
|
it.toUser()
|
||||||
|
}.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteFollowRequest(id: Long, follower: Long) {
|
||||||
|
FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean {
|
||||||
|
return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) }
|
||||||
|
.singleOrNull() != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun delete(id: Long) {
|
||||||
|
Users.deleteWhere { Users.id.eq(id) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun nextId(): Long = idGenerateService.generateId()
|
||||||
|
}
|
||||||
|
|
||||||
|
object Users : Table("users") {
|
||||||
|
val id = long("id")
|
||||||
|
val name = varchar("name", length = 64)
|
||||||
|
val domain = varchar("domain", length = 255)
|
||||||
|
val screenName = varchar("screen_name", length = 64)
|
||||||
|
val description = varchar("description", length = 600)
|
||||||
|
val password = varchar("password", length = 255).nullable()
|
||||||
|
val inbox = varchar("inbox", length = 255).uniqueIndex()
|
||||||
|
val outbox = varchar("outbox", length = 255).uniqueIndex()
|
||||||
|
val url = varchar("url", length = 255).uniqueIndex()
|
||||||
|
val publicKey = varchar("public_key", length = 10000)
|
||||||
|
val privateKey = varchar("private_key", length = 10000).nullable()
|
||||||
|
val createdAt = long("created_at")
|
||||||
|
|
||||||
|
override val primaryKey: PrimaryKey = PrimaryKey(id)
|
||||||
|
|
||||||
|
init {
|
||||||
|
uniqueIndex(name, domain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ResultRow.toUser(): User {
|
||||||
|
return User(
|
||||||
|
id = this[Users.id],
|
||||||
|
name = this[Users.name],
|
||||||
|
domain = this[Users.domain],
|
||||||
|
screenName = this[Users.screenName],
|
||||||
|
description = this[Users.description],
|
||||||
|
password = this[Users.password],
|
||||||
|
inbox = this[Users.inbox],
|
||||||
|
outbox = this[Users.outbox],
|
||||||
|
url = this[Users.url],
|
||||||
|
publicKey = this[Users.publicKey],
|
||||||
|
privateKey = this[Users.privateKey],
|
||||||
|
createdAt = Instant.ofEpochMilli((this[Users.createdAt]))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
object UsersFollowers : LongIdTable("users_followers") {
|
||||||
|
val userId = long("user_id").references(Users.id).index()
|
||||||
|
val followerId = long("follower_id").references(Users.id)
|
||||||
|
|
||||||
|
init {
|
||||||
|
uniqueIndex(userId, followerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object FollowRequests : LongIdTable("follow_requests") {
|
||||||
|
val userId = long("user_id").references(Users.id)
|
||||||
|
val followerId = long("follower_id").references(Users.id)
|
||||||
|
|
||||||
|
init {
|
||||||
|
uniqueIndex(userId, followerId)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package dev.usbharu.hideout.routing
|
package dev.usbharu.hideout.routing
|
||||||
|
|
||||||
import dev.usbharu.hideout.service.api.IUserApiService
|
import dev.usbharu.hideout.service.api.UserApiService
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.server.auth.*
|
import io.ktor.server.auth.*
|
||||||
|
@ -8,7 +8,7 @@ import io.ktor.server.request.*
|
||||||
import io.ktor.server.response.*
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Application.register(userApiService: IUserApiService) {
|
fun Application.register(userApiService: UserApiService) {
|
||||||
routing {
|
routing {
|
||||||
get("/register") {
|
get("/register") {
|
||||||
val principal = call.principal<UserIdPrincipal>()
|
val principal = call.principal<UserIdPrincipal>()
|
||||||
|
|
|
@ -13,7 +13,7 @@ import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Routing.inbox(
|
fun Routing.inbox(
|
||||||
httpSignatureVerifyService: HttpSignatureVerifyService,
|
httpSignatureVerifyService: HttpSignatureVerifyService,
|
||||||
activityPubService: dev.usbharu.hideout.service.activitypub.ActivityPubService
|
apService: dev.usbharu.hideout.service.ap.APService
|
||||||
) {
|
) {
|
||||||
route("/inbox") {
|
route("/inbox") {
|
||||||
get {
|
get {
|
||||||
|
@ -25,9 +25,9 @@ fun Routing.inbox(
|
||||||
}
|
}
|
||||||
val json = call.receiveText()
|
val json = call.receiveText()
|
||||||
call.application.log.trace("Received: $json")
|
call.application.log.trace("Received: $json")
|
||||||
val activityTypes = activityPubService.parseActivity(json)
|
val activityTypes = apService.parseActivity(json)
|
||||||
call.application.log.debug("ActivityTypes: ${activityTypes.name}")
|
call.application.log.debug("ActivityTypes: ${activityTypes.name}")
|
||||||
val response = activityPubService.processActivity(json, activityTypes)
|
val response = apService.processActivity(json, activityTypes)
|
||||||
when (response) {
|
when (response) {
|
||||||
is ActivityPubObjectResponse -> call.respond(
|
is ActivityPubObjectResponse -> call.respond(
|
||||||
response.httpStatusCode,
|
response.httpStatusCode,
|
||||||
|
@ -54,9 +54,9 @@ fun Routing.inbox(
|
||||||
}
|
}
|
||||||
val json = call.receiveText()
|
val json = call.receiveText()
|
||||||
call.application.log.trace("Received: $json")
|
call.application.log.trace("Received: $json")
|
||||||
val activityTypes = activityPubService.parseActivity(json)
|
val activityTypes = apService.parseActivity(json)
|
||||||
call.application.log.debug("ActivityTypes: ${activityTypes.name}")
|
call.application.log.debug("ActivityTypes: ${activityTypes.name}")
|
||||||
val response = activityPubService.processActivity(json, activityTypes)
|
val response = apService.processActivity(json, activityTypes)
|
||||||
when (response) {
|
when (response) {
|
||||||
is ActivityPubObjectResponse -> call.respond(
|
is ActivityPubObjectResponse -> call.respond(
|
||||||
response.httpStatusCode,
|
response.httpStatusCode,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import dev.usbharu.hideout.exception.ParameterNotExistException
|
||||||
import dev.usbharu.hideout.plugins.respondAp
|
import dev.usbharu.hideout.plugins.respondAp
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
import dev.usbharu.hideout.service.ap.APUserService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
import dev.usbharu.hideout.util.HttpUtil.Activity
|
||||||
import dev.usbharu.hideout.util.HttpUtil.JsonLd
|
import dev.usbharu.hideout.util.HttpUtil.JsonLd
|
||||||
|
@ -16,7 +16,7 @@ import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Routing.usersAP(
|
fun Routing.usersAP(
|
||||||
activityPubUserService: ActivityPubUserService,
|
apUserService: APUserService,
|
||||||
userQueryService: UserQueryService,
|
userQueryService: UserQueryService,
|
||||||
followerQueryService: FollowerQueryService,
|
followerQueryService: FollowerQueryService,
|
||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
|
@ -27,7 +27,7 @@ fun Routing.usersAP(
|
||||||
call.application.log.debug("Authorization: ${call.request.header("Authorization")}")
|
call.application.log.debug("Authorization: ${call.request.header("Authorization")}")
|
||||||
val name =
|
val name =
|
||||||
call.parameters["name"] ?: throw ParameterNotExistException("Parameter(name='name') does not exist.")
|
call.parameters["name"] ?: throw ParameterNotExistException("Parameter(name='name') does not exist.")
|
||||||
val person = activityPubUserService.getPersonByName(name)
|
val person = apUserService.getPersonByName(name)
|
||||||
return@handle call.respondAp(
|
return@handle call.respondAp(
|
||||||
person,
|
person,
|
||||||
HttpStatusCode.OK
|
HttpStatusCode.OK
|
||||||
|
|
|
@ -4,7 +4,7 @@ import dev.usbharu.hideout.domain.model.hideout.form.Post
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.Reaction
|
import dev.usbharu.hideout.domain.model.hideout.form.Reaction
|
||||||
import dev.usbharu.hideout.exception.ParameterNotExistException
|
import dev.usbharu.hideout.exception.ParameterNotExistException
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
import dev.usbharu.hideout.service.api.IPostApiService
|
import dev.usbharu.hideout.service.api.PostApiService
|
||||||
import dev.usbharu.hideout.util.InstantParseUtil
|
import dev.usbharu.hideout.util.InstantParseUtil
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
|
@ -15,7 +15,7 @@ import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
fun Route.posts(postApiService: IPostApiService) {
|
fun Route.posts(postApiService: PostApiService) {
|
||||||
route("/posts") {
|
route("/posts") {
|
||||||
authenticate(TOKEN_AUTH) {
|
authenticate(TOKEN_AUTH) {
|
||||||
post {
|
post {
|
||||||
|
|
|
@ -5,8 +5,8 @@ import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
|
import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
|
||||||
import dev.usbharu.hideout.exception.ParameterNotExistException
|
import dev.usbharu.hideout.exception.ParameterNotExistException
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
import dev.usbharu.hideout.service.api.IUserApiService
|
import dev.usbharu.hideout.service.api.UserApiService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import dev.usbharu.hideout.util.AcctUtil
|
import dev.usbharu.hideout.util.AcctUtil
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
|
@ -17,7 +17,7 @@ import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
@Suppress("LongMethod", "CognitiveComplexMethod")
|
@Suppress("LongMethod", "CognitiveComplexMethod")
|
||||||
fun Route.users(userService: IUserService, userApiService: IUserApiService) {
|
fun Route.users(userService: UserService, userApiService: UserApiService) {
|
||||||
route("/users") {
|
route("/users") {
|
||||||
get {
|
get {
|
||||||
call.respond(userApiService.findAll())
|
call.respond(userApiService.findAll())
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Accept
|
|
||||||
|
|
||||||
interface ActivityPubAcceptService {
|
|
||||||
suspend fun receiveAccept(accept: Accept): ActivityPubResponse
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Create
|
|
||||||
|
|
||||||
interface ActivityPubCreateService {
|
|
||||||
suspend fun receiveCreate(create: Create): ActivityPubResponse
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Like
|
|
||||||
|
|
||||||
interface ActivityPubLikeService {
|
|
||||||
suspend fun receiveLike(like: Like): ActivityPubResponse
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Note
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
|
||||||
import dev.usbharu.hideout.domain.model.job.DeliverPostJob
|
|
||||||
import kjob.core.job.JobProps
|
|
||||||
|
|
||||||
interface ActivityPubNoteService {
|
|
||||||
|
|
||||||
suspend fun createNote(post: Post)
|
|
||||||
suspend fun createNoteJob(props: JobProps<DeliverPostJob>)
|
|
||||||
|
|
||||||
suspend fun fetchNote(url: String, targetActor: String? = null): Note
|
|
||||||
suspend fun fetchNote(note: Note, targetActor: String? = null): Note
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
|
||||||
import dev.usbharu.hideout.domain.model.job.DeliverReactionJob
|
|
||||||
import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob
|
|
||||||
import kjob.core.job.JobProps
|
|
||||||
|
|
||||||
interface ActivityPubReactionService {
|
|
||||||
suspend fun reaction(like: Reaction)
|
|
||||||
suspend fun removeReaction(like: Reaction)
|
|
||||||
suspend fun reactionJob(props: JobProps<DeliverReactionJob>)
|
|
||||||
suspend fun removeReactionJob(props: JobProps<DeliverRemoveReactionJob>)
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Follow
|
|
||||||
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
|
|
||||||
import kjob.core.job.JobProps
|
|
||||||
|
|
||||||
interface ActivityPubReceiveFollowService {
|
|
||||||
suspend fun receiveFollow(follow: Follow): ActivityPubResponse
|
|
||||||
suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>)
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
|
||||||
|
|
||||||
interface ActivityPubSendFollowService {
|
|
||||||
suspend fun sendFollow(sendFollowDto: SendFollowDto)
|
|
||||||
}
|
|
|
@ -1,164 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.job.HideoutJob
|
|
||||||
import kjob.core.dsl.JobContextWithProps
|
|
||||||
|
|
||||||
interface ActivityPubService {
|
|
||||||
fun parseActivity(json: String): ActivityType
|
|
||||||
|
|
||||||
suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse?
|
|
||||||
|
|
||||||
suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ActivityType {
|
|
||||||
Accept,
|
|
||||||
Add,
|
|
||||||
Announce,
|
|
||||||
Arrive,
|
|
||||||
Block,
|
|
||||||
Create,
|
|
||||||
Delete,
|
|
||||||
Dislike,
|
|
||||||
Flag,
|
|
||||||
Follow,
|
|
||||||
Ignore,
|
|
||||||
Invite,
|
|
||||||
Join,
|
|
||||||
Leave,
|
|
||||||
Like,
|
|
||||||
Listen,
|
|
||||||
Move,
|
|
||||||
Offer,
|
|
||||||
Question,
|
|
||||||
Reject,
|
|
||||||
Read,
|
|
||||||
Remove,
|
|
||||||
TentativeReject,
|
|
||||||
TentativeAccept,
|
|
||||||
Travel,
|
|
||||||
Undo,
|
|
||||||
Update,
|
|
||||||
View,
|
|
||||||
Other
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ActivityVocabulary {
|
|
||||||
Object,
|
|
||||||
Link,
|
|
||||||
Activity,
|
|
||||||
IntransitiveActivity,
|
|
||||||
Collection,
|
|
||||||
OrderedCollection,
|
|
||||||
CollectionPage,
|
|
||||||
OrderedCollectionPage,
|
|
||||||
Accept,
|
|
||||||
Add,
|
|
||||||
Announce,
|
|
||||||
Arrive,
|
|
||||||
Block,
|
|
||||||
Create,
|
|
||||||
Delete,
|
|
||||||
Dislike,
|
|
||||||
Flag,
|
|
||||||
Follow,
|
|
||||||
Ignore,
|
|
||||||
Invite,
|
|
||||||
Join,
|
|
||||||
Leave,
|
|
||||||
Like,
|
|
||||||
Listen,
|
|
||||||
Move,
|
|
||||||
Offer,
|
|
||||||
Question,
|
|
||||||
Reject,
|
|
||||||
Read,
|
|
||||||
Remove,
|
|
||||||
TentativeReject,
|
|
||||||
TentativeAccept,
|
|
||||||
Travel,
|
|
||||||
Undo,
|
|
||||||
Update,
|
|
||||||
View,
|
|
||||||
Application,
|
|
||||||
Group,
|
|
||||||
Organization,
|
|
||||||
Person,
|
|
||||||
Service,
|
|
||||||
Article,
|
|
||||||
Audio,
|
|
||||||
Document,
|
|
||||||
Event,
|
|
||||||
Image,
|
|
||||||
Note,
|
|
||||||
Page,
|
|
||||||
Place,
|
|
||||||
Profile,
|
|
||||||
Relationship,
|
|
||||||
Tombstone,
|
|
||||||
Video,
|
|
||||||
Mention,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ExtendedActivityVocabulary {
|
|
||||||
Object,
|
|
||||||
Link,
|
|
||||||
Activity,
|
|
||||||
IntransitiveActivity,
|
|
||||||
Collection,
|
|
||||||
OrderedCollection,
|
|
||||||
CollectionPage,
|
|
||||||
OrderedCollectionPage,
|
|
||||||
Accept,
|
|
||||||
Add,
|
|
||||||
Announce,
|
|
||||||
Arrive,
|
|
||||||
Block,
|
|
||||||
Create,
|
|
||||||
Delete,
|
|
||||||
Dislike,
|
|
||||||
Flag,
|
|
||||||
Follow,
|
|
||||||
Ignore,
|
|
||||||
Invite,
|
|
||||||
Join,
|
|
||||||
Leave,
|
|
||||||
Like,
|
|
||||||
Listen,
|
|
||||||
Move,
|
|
||||||
Offer,
|
|
||||||
Question,
|
|
||||||
Reject,
|
|
||||||
Read,
|
|
||||||
Remove,
|
|
||||||
TentativeReject,
|
|
||||||
TentativeAccept,
|
|
||||||
Travel,
|
|
||||||
Undo,
|
|
||||||
Update,
|
|
||||||
View,
|
|
||||||
Application,
|
|
||||||
Group,
|
|
||||||
Organization,
|
|
||||||
Person,
|
|
||||||
Service,
|
|
||||||
Article,
|
|
||||||
Audio,
|
|
||||||
Document,
|
|
||||||
Event,
|
|
||||||
Image,
|
|
||||||
Note,
|
|
||||||
Page,
|
|
||||||
Place,
|
|
||||||
Profile,
|
|
||||||
Relationship,
|
|
||||||
Tombstone,
|
|
||||||
Video,
|
|
||||||
Mention,
|
|
||||||
Emoji
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ExtendedVocabulary {
|
|
||||||
Emoji
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
|
||||||
import dev.usbharu.hideout.config.Config.configData
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Follow
|
|
||||||
import dev.usbharu.hideout.domain.model.job.*
|
|
||||||
import dev.usbharu.hideout.exception.JsonParseException
|
|
||||||
import kjob.core.dsl.JobContextWithProps
|
|
||||||
import kjob.core.job.JobProps
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
import org.slf4j.Logger
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class ActivityPubServiceImpl(
|
|
||||||
private val activityPubReceiveFollowService: ActivityPubReceiveFollowService,
|
|
||||||
private val activityPubNoteService: ActivityPubNoteService,
|
|
||||||
private val activityPubUndoService: ActivityPubUndoService,
|
|
||||||
private val activityPubAcceptService: ActivityPubAcceptService,
|
|
||||||
private val activityPubCreateService: ActivityPubCreateService,
|
|
||||||
private val activityPubLikeService: ActivityPubLikeService,
|
|
||||||
private val activityPubReactionService: ActivityPubReactionService
|
|
||||||
) : ActivityPubService {
|
|
||||||
|
|
||||||
val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
|
||||||
override fun parseActivity(json: String): ActivityType {
|
|
||||||
val readTree = configData.objectMapper.readTree(json)
|
|
||||||
logger.trace("readTree: {}", readTree)
|
|
||||||
if (readTree.isObject.not()) {
|
|
||||||
throw JsonParseException("Json is not object.")
|
|
||||||
}
|
|
||||||
val type = readTree["type"]
|
|
||||||
if (type.isArray) {
|
|
||||||
return type.firstNotNullOf { jsonNode: JsonNode ->
|
|
||||||
ActivityType.values().firstOrNull { it.name.equals(jsonNode.asText(), true) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ActivityType.values().first { it.name.equals(type.asText(), true) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("CyclomaticComplexMethod", "NotImplementedDeclaration")
|
|
||||||
override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse {
|
|
||||||
logger.debug("proccess activity: {}", type)
|
|
||||||
return when (type) {
|
|
||||||
ActivityType.Accept -> activityPubAcceptService.receiveAccept(configData.objectMapper.readValue(json))
|
|
||||||
ActivityType.Follow -> activityPubReceiveFollowService.receiveFollow(
|
|
||||||
configData.objectMapper.readValue(
|
|
||||||
json,
|
|
||||||
Follow::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
ActivityType.Create -> activityPubCreateService.receiveCreate(configData.objectMapper.readValue(json))
|
|
||||||
ActivityType.Like -> activityPubLikeService.receiveLike(configData.objectMapper.readValue(json))
|
|
||||||
ActivityType.Undo -> activityPubUndoService.receiveUndo(configData.objectMapper.readValue(json))
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
throw IllegalArgumentException("$type is not supported.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob) {
|
|
||||||
logger.debug("processActivity: ${hideoutJob.name}")
|
|
||||||
when (hideoutJob) {
|
|
||||||
ReceiveFollowJob -> activityPubReceiveFollowService.receiveFollowJob(
|
|
||||||
job.props as JobProps<ReceiveFollowJob>
|
|
||||||
)
|
|
||||||
|
|
||||||
DeliverPostJob -> activityPubNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>)
|
|
||||||
DeliverReactionJob -> activityPubReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>)
|
|
||||||
DeliverRemoveReactionJob -> activityPubReactionService.removeReactionJob(
|
|
||||||
job.props as JobProps<DeliverRemoveReactionJob>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Undo
|
|
||||||
|
|
||||||
interface ActivityPubUndoService {
|
|
||||||
suspend fun receiveUndo(undo: Undo): ActivityPubResponse
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Person
|
|
||||||
|
|
||||||
interface ActivityPubUserService {
|
|
||||||
suspend fun getPersonByName(name: String): Person
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch person
|
|
||||||
*
|
|
||||||
* @param url
|
|
||||||
* @param targetActor 署名するユーザー
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
suspend fun fetchPerson(url: String, targetActor: String? = null): Person
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
||||||
|
@ -6,15 +6,19 @@ import dev.usbharu.hideout.domain.model.ap.Accept
|
||||||
import dev.usbharu.hideout.domain.model.ap.Follow
|
import dev.usbharu.hideout.domain.model.ap.Follow
|
||||||
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APAcceptService {
|
||||||
|
suspend fun receiveAccept(accept: Accept): ActivityPubResponse
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubAcceptServiceImpl(
|
class APAcceptServiceImpl(
|
||||||
private val userService: IUserService,
|
private val userService: UserService,
|
||||||
private val userQueryService: UserQueryService
|
private val userQueryService: UserQueryService
|
||||||
) : ActivityPubAcceptService {
|
) : APAcceptService {
|
||||||
override suspend fun receiveAccept(accept: Accept): ActivityPubResponse {
|
override suspend fun receiveAccept(accept: Accept): ActivityPubResponse {
|
||||||
val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
if (value.type.contains("Follow").not()) {
|
if (value.type.contains("Follow").not()) {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
||||||
|
@ -9,11 +9,15 @@ import dev.usbharu.hideout.service.core.Transaction
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APCreateService {
|
||||||
|
suspend fun receiveCreate(create: Create): ActivityPubResponse
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubCreateServiceImpl(
|
class APCreateServiceImpl(
|
||||||
private val activityPubNoteService: ActivityPubNoteService,
|
private val apNoteService: APNoteService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : ActivityPubCreateService {
|
) : APCreateService {
|
||||||
override suspend fun receiveCreate(create: Create): ActivityPubResponse {
|
override suspend fun receiveCreate(create: Create): ActivityPubResponse {
|
||||||
val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
if (value.type.contains("Note").not()) {
|
if (value.type.contains("Note").not()) {
|
||||||
|
@ -22,7 +26,7 @@ class ActivityPubCreateServiceImpl(
|
||||||
|
|
||||||
return transaction.transaction {
|
return transaction.transaction {
|
||||||
val note = value as Note
|
val note = value as Note
|
||||||
activityPubNoteService.fetchNote(note)
|
apNoteService.fetchNote(note)
|
||||||
ActivityPubStringResponse(HttpStatusCode.OK, "Created")
|
ActivityPubStringResponse(HttpStatusCode.OK, "Created")
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
||||||
|
@ -7,26 +7,30 @@ import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.query.PostQueryService
|
import dev.usbharu.hideout.query.PostQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.reaction.IReactionService
|
import dev.usbharu.hideout.service.reaction.ReactionService
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APLikeService {
|
||||||
|
suspend fun receiveLike(like: Like): ActivityPubResponse
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubLikeServiceImpl(
|
class APLikeServiceImpl(
|
||||||
private val reactionService: IReactionService,
|
private val reactionService: ReactionService,
|
||||||
private val activityPubUserService: ActivityPubUserService,
|
private val apUserService: APUserService,
|
||||||
private val activityPubNoteService: ActivityPubNoteService,
|
private val apNoteService: APNoteService,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val postQueryService: PostQueryService,
|
private val postQueryService: PostQueryService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : ActivityPubLikeService {
|
) : APLikeService {
|
||||||
override suspend fun receiveLike(like: Like): ActivityPubResponse {
|
override suspend fun receiveLike(like: Like): ActivityPubResponse {
|
||||||
val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null")
|
||||||
val content = like.content ?: throw IllegalActivityPubObjectException("content is null")
|
val content = like.content ?: throw IllegalActivityPubObjectException("content is null")
|
||||||
like.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
like.`object` ?: throw IllegalActivityPubObjectException("object is null")
|
||||||
transaction.transaction {
|
transaction.transaction {
|
||||||
val person = activityPubUserService.fetchPerson(actor)
|
val person = apUserService.fetchPerson(actor)
|
||||||
activityPubNoteService.fetchNote(like.`object`!!)
|
apNoteService.fetchNote(like.`object`!!)
|
||||||
|
|
||||||
val user = userQueryService.findByUrl(
|
val user = userQueryService.findByUrl(
|
||||||
person.url
|
person.url
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
|
@ -13,7 +13,7 @@ import dev.usbharu.hideout.plugins.postAp
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.PostQueryService
|
import dev.usbharu.hideout.query.PostQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.repository.IPostRepository
|
import dev.usbharu.hideout.repository.PostRepository
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.statement.*
|
||||||
|
@ -22,16 +22,25 @@ import org.koin.core.annotation.Single
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
|
interface APNoteService {
|
||||||
|
|
||||||
|
suspend fun createNote(post: Post)
|
||||||
|
suspend fun createNoteJob(props: JobProps<DeliverPostJob>)
|
||||||
|
|
||||||
|
suspend fun fetchNote(url: String, targetActor: String? = null): Note
|
||||||
|
suspend fun fetchNote(note: Note, targetActor: String? = null): Note
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubNoteServiceImpl(
|
class APNoteServiceImpl(
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val jobQueueParentService: JobQueueParentService,
|
private val jobQueueParentService: JobQueueParentService,
|
||||||
private val postRepository: IPostRepository,
|
private val postRepository: PostRepository,
|
||||||
private val activityPubUserService: ActivityPubUserService,
|
private val apUserService: APUserService,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val followerQueryService: FollowerQueryService,
|
private val followerQueryService: FollowerQueryService,
|
||||||
private val postQueryService: PostQueryService
|
private val postQueryService: PostQueryService
|
||||||
) : ActivityPubNoteService {
|
) : APNoteService {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
|
||||||
|
@ -41,9 +50,9 @@ class ActivityPubNoteServiceImpl(
|
||||||
val note = Config.configData.objectMapper.writeValueAsString(post)
|
val note = Config.configData.objectMapper.writeValueAsString(post)
|
||||||
followers.forEach { followerEntity ->
|
followers.forEach { followerEntity ->
|
||||||
jobQueueParentService.schedule(DeliverPostJob) {
|
jobQueueParentService.schedule(DeliverPostJob) {
|
||||||
props[it.actor] = userEntity.url
|
props[DeliverPostJob.actor] = userEntity.url
|
||||||
props[it.post] = note
|
props[DeliverPostJob.post] = note
|
||||||
props[it.inbox] = followerEntity.inbox
|
props[DeliverPostJob.inbox] = followerEntity.inbox
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,9 +84,12 @@ class ActivityPubNoteServiceImpl(
|
||||||
|
|
||||||
override suspend fun fetchNote(url: String, targetActor: String?): Note {
|
override suspend fun fetchNote(url: String, targetActor: String?): Note {
|
||||||
val post = postQueryService.findByUrl(url)
|
val post = postQueryService.findByUrl(url)
|
||||||
if (post != null) {
|
try {
|
||||||
return postToNote(post)
|
return postToNote(post)
|
||||||
|
} catch (_: NoSuchElementException) {
|
||||||
|
} catch (_: IllegalArgumentException) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = httpClient.getAp(
|
val response = httpClient.getAp(
|
||||||
url,
|
url,
|
||||||
targetActor?.let { "$targetActor#pubkey" }
|
targetActor?.let { "$targetActor#pubkey" }
|
||||||
|
@ -118,7 +130,7 @@ class ActivityPubNoteServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun internalNote(note: Note, targetActor: String?, url: String): Note {
|
private suspend fun internalNote(note: Note, targetActor: String?, url: String): Note {
|
||||||
val person = activityPubUserService.fetchPerson(
|
val person = apUserService.fetchPerson(
|
||||||
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
|
note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"),
|
||||||
targetActor
|
targetActor
|
||||||
)
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
|
@ -11,22 +11,29 @@ import dev.usbharu.hideout.plugins.postAp
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.PostQueryService
|
import dev.usbharu.hideout.query.PostQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.repository.IPostRepository
|
import dev.usbharu.hideout.repository.PostRepository
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import kjob.core.job.JobProps
|
import kjob.core.job.JobProps
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
|
interface APReactionService {
|
||||||
|
suspend fun reaction(like: Reaction)
|
||||||
|
suspend fun removeReaction(like: Reaction)
|
||||||
|
suspend fun reactionJob(props: JobProps<DeliverReactionJob>)
|
||||||
|
suspend fun removeReactionJob(props: JobProps<DeliverRemoveReactionJob>)
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubReactionServiceImpl(
|
class APReactionServiceImpl(
|
||||||
private val jobQueueParentService: JobQueueParentService,
|
private val jobQueueParentService: JobQueueParentService,
|
||||||
private val iPostRepository: IPostRepository,
|
private val postRepository: PostRepository,
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val followerQueryService: FollowerQueryService,
|
private val followerQueryService: FollowerQueryService,
|
||||||
private val postQueryService: PostQueryService
|
private val postQueryService: PostQueryService
|
||||||
) : ActivityPubReactionService {
|
) : APReactionService {
|
||||||
override suspend fun reaction(like: Reaction) {
|
override suspend fun reaction(like: Reaction) {
|
||||||
val followers = followerQueryService.findFollowersById(like.userId)
|
val followers = followerQueryService.findFollowersById(like.userId)
|
||||||
val user = userQueryService.findById(like.userId)
|
val user = userQueryService.findById(like.userId)
|
||||||
|
@ -34,11 +41,11 @@ class ActivityPubReactionServiceImpl(
|
||||||
postQueryService.findById(like.postId)
|
postQueryService.findById(like.postId)
|
||||||
followers.forEach { follower ->
|
followers.forEach { follower ->
|
||||||
jobQueueParentService.schedule(DeliverReactionJob) {
|
jobQueueParentService.schedule(DeliverReactionJob) {
|
||||||
props[it.actor] = user.url
|
props[DeliverReactionJob.actor] = user.url
|
||||||
props[it.reaction] = "❤"
|
props[DeliverReactionJob.reaction] = "❤"
|
||||||
props[it.inbox] = follower.inbox
|
props[DeliverReactionJob.inbox] = follower.inbox
|
||||||
props[it.postUrl] = post.url
|
props[DeliverReactionJob.postUrl] = post.url
|
||||||
props[it.id] = post.id.toString()
|
props[DeliverReactionJob.id] = post.id.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,10 +57,10 @@ class ActivityPubReactionServiceImpl(
|
||||||
postQueryService.findById(like.postId)
|
postQueryService.findById(like.postId)
|
||||||
followers.forEach { follower ->
|
followers.forEach { follower ->
|
||||||
jobQueueParentService.schedule(DeliverRemoveReactionJob) {
|
jobQueueParentService.schedule(DeliverRemoveReactionJob) {
|
||||||
props[it.actor] = user.url
|
props[DeliverRemoveReactionJob.actor] = user.url
|
||||||
props[it.inbox] = follower.inbox
|
props[DeliverRemoveReactionJob.inbox] = follower.inbox
|
||||||
props[it.id] = post.id.toString()
|
props[DeliverRemoveReactionJob.id] = post.id.toString()
|
||||||
props[it.like] = Config.configData.objectMapper.writeValueAsString(like)
|
props[DeliverRemoveReactionJob.like] = Config.configData.objectMapper.writeValueAsString(like)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
|
@ -11,27 +11,32 @@ import dev.usbharu.hideout.plugins.postAp
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import kjob.core.job.JobProps
|
import kjob.core.job.JobProps
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APReceiveFollowService {
|
||||||
|
suspend fun receiveFollow(follow: Follow): ActivityPubResponse
|
||||||
|
suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>)
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubReceiveFollowServiceImpl(
|
class APReceiveFollowServiceImpl(
|
||||||
private val jobQueueParentService: JobQueueParentService,
|
private val jobQueueParentService: JobQueueParentService,
|
||||||
private val activityPubUserService: ActivityPubUserService,
|
private val apUserService: APUserService,
|
||||||
private val userService: IUserService,
|
private val userService: UserService,
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : ActivityPubReceiveFollowService {
|
) : APReceiveFollowService {
|
||||||
override suspend fun receiveFollow(follow: Follow): ActivityPubResponse {
|
override suspend fun receiveFollow(follow: Follow): ActivityPubResponse {
|
||||||
// TODO: Verify HTTP Signature
|
// TODO: Verify HTTP Signature
|
||||||
jobQueueParentService.schedule(ReceiveFollowJob) {
|
jobQueueParentService.schedule(ReceiveFollowJob) {
|
||||||
props[it.actor] = follow.actor
|
props[ReceiveFollowJob.actor] = follow.actor
|
||||||
props[it.follow] = Config.configData.objectMapper.writeValueAsString(follow)
|
props[ReceiveFollowJob.follow] = Config.configData.objectMapper.writeValueAsString(follow)
|
||||||
props[it.targetActor] = follow.`object`
|
props[ReceiveFollowJob.targetActor] = follow.`object`
|
||||||
}
|
}
|
||||||
return ActivityPubStringResponse(HttpStatusCode.OK, "{}", ContentType.Application.Json)
|
return ActivityPubStringResponse(HttpStatusCode.OK, "{}", ContentType.Application.Json)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +45,7 @@ class ActivityPubReceiveFollowServiceImpl(
|
||||||
transaction.transaction {
|
transaction.transaction {
|
||||||
val actor = props[ReceiveFollowJob.actor]
|
val actor = props[ReceiveFollowJob.actor]
|
||||||
val targetActor = props[ReceiveFollowJob.targetActor]
|
val targetActor = props[ReceiveFollowJob.targetActor]
|
||||||
val person = activityPubUserService.fetchPerson(actor, targetActor)
|
val person = apUserService.fetchPerson(actor, targetActor)
|
||||||
val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow])
|
val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow])
|
||||||
httpClient.postAp(
|
httpClient.postAp(
|
||||||
urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"),
|
urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"),
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Follow
|
import dev.usbharu.hideout.domain.model.ap.Follow
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
||||||
|
@ -6,8 +6,12 @@ import dev.usbharu.hideout.plugins.postAp
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APSendFollowService {
|
||||||
|
suspend fun sendFollow(sendFollowDto: SendFollowDto)
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubSendFollowServiceImpl(private val httpClient: HttpClient) : ActivityPubSendFollowService {
|
class APSendFollowServiceImpl(private val httpClient: HttpClient) : APSendFollowService {
|
||||||
override suspend fun sendFollow(sendFollowDto: SendFollowDto) {
|
override suspend fun sendFollow(sendFollowDto: SendFollowDto) {
|
||||||
val follow = Follow(
|
val follow = Follow(
|
||||||
name = "Follow",
|
name = "Follow",
|
|
@ -0,0 +1,238 @@
|
||||||
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
||||||
|
import dev.usbharu.hideout.domain.model.ap.Follow
|
||||||
|
import dev.usbharu.hideout.domain.model.job.*
|
||||||
|
import dev.usbharu.hideout.exception.JsonParseException
|
||||||
|
import kjob.core.dsl.JobContextWithProps
|
||||||
|
import kjob.core.job.JobProps
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
interface APService {
|
||||||
|
fun parseActivity(json: String): ActivityType
|
||||||
|
|
||||||
|
suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse?
|
||||||
|
|
||||||
|
suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ActivityType {
|
||||||
|
Accept,
|
||||||
|
Add,
|
||||||
|
Announce,
|
||||||
|
Arrive,
|
||||||
|
Block,
|
||||||
|
Create,
|
||||||
|
Delete,
|
||||||
|
Dislike,
|
||||||
|
Flag,
|
||||||
|
Follow,
|
||||||
|
Ignore,
|
||||||
|
Invite,
|
||||||
|
Join,
|
||||||
|
Leave,
|
||||||
|
Like,
|
||||||
|
Listen,
|
||||||
|
Move,
|
||||||
|
Offer,
|
||||||
|
Question,
|
||||||
|
Reject,
|
||||||
|
Read,
|
||||||
|
Remove,
|
||||||
|
TentativeReject,
|
||||||
|
TentativeAccept,
|
||||||
|
Travel,
|
||||||
|
Undo,
|
||||||
|
Update,
|
||||||
|
View,
|
||||||
|
Other
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ActivityVocabulary {
|
||||||
|
Object,
|
||||||
|
Link,
|
||||||
|
Activity,
|
||||||
|
IntransitiveActivity,
|
||||||
|
Collection,
|
||||||
|
OrderedCollection,
|
||||||
|
CollectionPage,
|
||||||
|
OrderedCollectionPage,
|
||||||
|
Accept,
|
||||||
|
Add,
|
||||||
|
Announce,
|
||||||
|
Arrive,
|
||||||
|
Block,
|
||||||
|
Create,
|
||||||
|
Delete,
|
||||||
|
Dislike,
|
||||||
|
Flag,
|
||||||
|
Follow,
|
||||||
|
Ignore,
|
||||||
|
Invite,
|
||||||
|
Join,
|
||||||
|
Leave,
|
||||||
|
Like,
|
||||||
|
Listen,
|
||||||
|
Move,
|
||||||
|
Offer,
|
||||||
|
Question,
|
||||||
|
Reject,
|
||||||
|
Read,
|
||||||
|
Remove,
|
||||||
|
TentativeReject,
|
||||||
|
TentativeAccept,
|
||||||
|
Travel,
|
||||||
|
Undo,
|
||||||
|
Update,
|
||||||
|
View,
|
||||||
|
Application,
|
||||||
|
Group,
|
||||||
|
Organization,
|
||||||
|
Person,
|
||||||
|
Service,
|
||||||
|
Article,
|
||||||
|
Audio,
|
||||||
|
Document,
|
||||||
|
Event,
|
||||||
|
Image,
|
||||||
|
Note,
|
||||||
|
Page,
|
||||||
|
Place,
|
||||||
|
Profile,
|
||||||
|
Relationship,
|
||||||
|
Tombstone,
|
||||||
|
Video,
|
||||||
|
Mention,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ExtendedActivityVocabulary {
|
||||||
|
Object,
|
||||||
|
Link,
|
||||||
|
Activity,
|
||||||
|
IntransitiveActivity,
|
||||||
|
Collection,
|
||||||
|
OrderedCollection,
|
||||||
|
CollectionPage,
|
||||||
|
OrderedCollectionPage,
|
||||||
|
Accept,
|
||||||
|
Add,
|
||||||
|
Announce,
|
||||||
|
Arrive,
|
||||||
|
Block,
|
||||||
|
Create,
|
||||||
|
Delete,
|
||||||
|
Dislike,
|
||||||
|
Flag,
|
||||||
|
Follow,
|
||||||
|
Ignore,
|
||||||
|
Invite,
|
||||||
|
Join,
|
||||||
|
Leave,
|
||||||
|
Like,
|
||||||
|
Listen,
|
||||||
|
Move,
|
||||||
|
Offer,
|
||||||
|
Question,
|
||||||
|
Reject,
|
||||||
|
Read,
|
||||||
|
Remove,
|
||||||
|
TentativeReject,
|
||||||
|
TentativeAccept,
|
||||||
|
Travel,
|
||||||
|
Undo,
|
||||||
|
Update,
|
||||||
|
View,
|
||||||
|
Application,
|
||||||
|
Group,
|
||||||
|
Organization,
|
||||||
|
Person,
|
||||||
|
Service,
|
||||||
|
Article,
|
||||||
|
Audio,
|
||||||
|
Document,
|
||||||
|
Event,
|
||||||
|
Image,
|
||||||
|
Note,
|
||||||
|
Page,
|
||||||
|
Place,
|
||||||
|
Profile,
|
||||||
|
Relationship,
|
||||||
|
Tombstone,
|
||||||
|
Video,
|
||||||
|
Mention,
|
||||||
|
Emoji
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ExtendedVocabulary {
|
||||||
|
Emoji
|
||||||
|
}
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class APServiceImpl(
|
||||||
|
private val apReceiveFollowService: APReceiveFollowService,
|
||||||
|
private val apNoteService: APNoteService,
|
||||||
|
private val apUndoService: APUndoService,
|
||||||
|
private val apAcceptService: APAcceptService,
|
||||||
|
private val apCreateService: APCreateService,
|
||||||
|
private val apLikeService: APLikeService,
|
||||||
|
private val apReactionService: APReactionService
|
||||||
|
) : APService {
|
||||||
|
|
||||||
|
val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
||||||
|
override fun parseActivity(json: String): ActivityType {
|
||||||
|
val readTree = Config.configData.objectMapper.readTree(json)
|
||||||
|
logger.trace("readTree: {}", readTree)
|
||||||
|
if (readTree.isObject.not()) {
|
||||||
|
throw JsonParseException("Json is not object.")
|
||||||
|
}
|
||||||
|
val type = readTree["type"]
|
||||||
|
if (type.isArray) {
|
||||||
|
return type.firstNotNullOf { jsonNode: JsonNode ->
|
||||||
|
ActivityType.values().firstOrNull { it.name.equals(jsonNode.asText(), true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ActivityType.values().first { it.name.equals(type.asText(), true) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("CyclomaticComplexMethod", "NotImplementedDeclaration")
|
||||||
|
override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse {
|
||||||
|
logger.debug("proccess activity: {}", type)
|
||||||
|
return when (type) {
|
||||||
|
ActivityType.Accept -> apAcceptService.receiveAccept(Config.configData.objectMapper.readValue(json))
|
||||||
|
ActivityType.Follow -> apReceiveFollowService.receiveFollow(
|
||||||
|
Config.configData.objectMapper.readValue(
|
||||||
|
json,
|
||||||
|
Follow::class.java
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ActivityType.Create -> apCreateService.receiveCreate(Config.configData.objectMapper.readValue(json))
|
||||||
|
ActivityType.Like -> apLikeService.receiveLike(Config.configData.objectMapper.readValue(json))
|
||||||
|
ActivityType.Undo -> apUndoService.receiveUndo(Config.configData.objectMapper.readValue(json))
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
throw IllegalArgumentException("$type is not supported.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob) {
|
||||||
|
logger.debug("processActivity: ${hideoutJob.name}")
|
||||||
|
when (hideoutJob) {
|
||||||
|
ReceiveFollowJob -> apReceiveFollowService.receiveFollowJob(
|
||||||
|
job.props as JobProps<ReceiveFollowJob>
|
||||||
|
)
|
||||||
|
|
||||||
|
DeliverPostJob -> apNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>)
|
||||||
|
DeliverReactionJob -> apReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>)
|
||||||
|
DeliverRemoveReactionJob -> apReactionService.removeReactionJob(
|
||||||
|
job.props as JobProps<DeliverRemoveReactionJob>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubResponse
|
||||||
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
|
||||||
|
@ -6,18 +6,22 @@ import dev.usbharu.hideout.domain.model.ap.Follow
|
||||||
import dev.usbharu.hideout.domain.model.ap.Undo
|
import dev.usbharu.hideout.domain.model.ap.Undo
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APUndoService {
|
||||||
|
suspend fun receiveUndo(undo: Undo): ActivityPubResponse
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
@Suppress("UnsafeCallOnNullableType")
|
@Suppress("UnsafeCallOnNullableType")
|
||||||
class ActivityPubUndoServiceImpl(
|
class APUndoServiceImpl(
|
||||||
private val userService: IUserService,
|
private val userService: UserService,
|
||||||
private val activityPubUserService: ActivityPubUserService,
|
private val apUserService: APUserService,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : ActivityPubUndoService {
|
) : APUndoService {
|
||||||
override suspend fun receiveUndo(undo: Undo): ActivityPubResponse {
|
override suspend fun receiveUndo(undo: Undo): ActivityPubResponse {
|
||||||
if (undo.actor == null) {
|
if (undo.actor == null) {
|
||||||
return ActivityPubStringResponse(HttpStatusCode.BadRequest, "actor is null")
|
return ActivityPubStringResponse(HttpStatusCode.BadRequest, "actor is null")
|
||||||
|
@ -36,7 +40,7 @@ class ActivityPubUndoServiceImpl(
|
||||||
return ActivityPubStringResponse(HttpStatusCode.BadRequest, "object.object is null")
|
return ActivityPubStringResponse(HttpStatusCode.BadRequest, "object.object is null")
|
||||||
}
|
}
|
||||||
transaction.transaction {
|
transaction.transaction {
|
||||||
activityPubUserService.fetchPerson(undo.actor!!, follow.`object`)
|
apUserService.fetchPerson(undo.actor!!, follow.`object`)
|
||||||
val follower = userQueryService.findByUrl(undo.actor!!)
|
val follower = userQueryService.findByUrl(undo.actor!!)
|
||||||
val target = userQueryService.findByUrl(follow.`object`!!)
|
val target = userQueryService.findByUrl(follow.`object`!!)
|
||||||
userService.unfollow(target.id, follower.id)
|
userService.unfollow(target.id, follower.id)
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
|
@ -10,7 +10,7 @@ import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
|
||||||
import dev.usbharu.hideout.plugins.getAp
|
import dev.usbharu.hideout.plugins.getAp
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
import dev.usbharu.hideout.util.HttpUtil.Activity
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
|
@ -18,14 +18,27 @@ import io.ktor.client.statement.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
|
interface APUserService {
|
||||||
|
suspend fun getPersonByName(name: String): Person
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch person
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param targetActor 署名するユーザー
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
suspend fun fetchPerson(url: String, targetActor: String? = null): Person
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ActivityPubUserServiceImpl(
|
class APUserServiceImpl(
|
||||||
private val userService: IUserService,
|
private val userService: UserService,
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) :
|
) :
|
||||||
ActivityPubUserService {
|
APUserService {
|
||||||
|
|
||||||
override suspend fun getPersonByName(name: String): Person {
|
override suspend fun getPersonByName(name: String): Person {
|
||||||
val userEntity = transaction.transaction {
|
val userEntity = transaction.transaction {
|
|
@ -1,33 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.api
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
|
||||||
interface IPostApiService {
|
|
||||||
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): PostResponse
|
|
||||||
suspend fun getById(id: Long, userId: Long?): PostResponse
|
|
||||||
suspend fun getAll(
|
|
||||||
since: Instant? = null,
|
|
||||||
until: Instant? = null,
|
|
||||||
minId: Long? = null,
|
|
||||||
maxId: Long? = null,
|
|
||||||
limit: Int? = null,
|
|
||||||
userId: Long? = null
|
|
||||||
): List<PostResponse>
|
|
||||||
|
|
||||||
suspend fun getByUser(
|
|
||||||
nameOrId: String,
|
|
||||||
since: Instant? = null,
|
|
||||||
until: Instant? = null,
|
|
||||||
minId: Long? = null,
|
|
||||||
maxId: Long? = null,
|
|
||||||
limit: Int? = null,
|
|
||||||
userId: Long? = null
|
|
||||||
): List<PostResponse>
|
|
||||||
|
|
||||||
suspend fun getReactionByPostId(postId: Long, userId: Long? = null): List<ReactionResponse>
|
|
||||||
suspend fun appendReaction(reaction: String, userId: Long, postId: Long)
|
|
||||||
suspend fun removeReaction(userId: Long, postId: Long)
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.api
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.Acct
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
|
|
||||||
|
|
||||||
interface IUserApiService {
|
|
||||||
suspend fun findAll(limit: Int? = 100, offset: Long = 0): List<UserResponse>
|
|
||||||
|
|
||||||
suspend fun findById(id: Long): UserResponse
|
|
||||||
|
|
||||||
suspend fun findByIds(ids: List<Long>): List<UserResponse>
|
|
||||||
|
|
||||||
suspend fun findByAcct(acct: Acct): UserResponse
|
|
||||||
|
|
||||||
suspend fun findFollowers(userId: Long): List<UserResponse>
|
|
||||||
|
|
||||||
suspend fun findFollowings(userId: Long): List<UserResponse>
|
|
||||||
|
|
||||||
suspend fun findFollowersByAcct(acct: Acct): List<UserResponse>
|
|
||||||
|
|
||||||
suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse>
|
|
||||||
|
|
||||||
suspend fun createUser(username: String, password: String): UserResponse
|
|
||||||
}
|
|
|
@ -4,27 +4,55 @@ import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse
|
import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.form.Post
|
||||||
import dev.usbharu.hideout.query.PostResponseQueryService
|
import dev.usbharu.hideout.query.PostResponseQueryService
|
||||||
import dev.usbharu.hideout.query.ReactionQueryService
|
import dev.usbharu.hideout.query.ReactionQueryService
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
import dev.usbharu.hideout.repository.UserRepository
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.post.IPostService
|
import dev.usbharu.hideout.service.post.PostService
|
||||||
import dev.usbharu.hideout.service.reaction.IReactionService
|
import dev.usbharu.hideout.service.reaction.ReactionService
|
||||||
import dev.usbharu.hideout.util.AcctUtil
|
import dev.usbharu.hideout.util.AcctUtil
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.Post as FormPost
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
|
interface PostApiService {
|
||||||
|
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): PostResponse
|
||||||
|
suspend fun getById(id: Long, userId: Long?): PostResponse
|
||||||
|
suspend fun getAll(
|
||||||
|
since: Instant? = null,
|
||||||
|
until: Instant? = null,
|
||||||
|
minId: Long? = null,
|
||||||
|
maxId: Long? = null,
|
||||||
|
limit: Int? = null,
|
||||||
|
userId: Long? = null
|
||||||
|
): List<PostResponse>
|
||||||
|
|
||||||
|
suspend fun getByUser(
|
||||||
|
nameOrId: String,
|
||||||
|
since: Instant? = null,
|
||||||
|
until: Instant? = null,
|
||||||
|
minId: Long? = null,
|
||||||
|
maxId: Long? = null,
|
||||||
|
limit: Int? = null,
|
||||||
|
userId: Long? = null
|
||||||
|
): List<PostResponse>
|
||||||
|
|
||||||
|
suspend fun getReactionByPostId(postId: Long, userId: Long? = null): List<ReactionResponse>
|
||||||
|
suspend fun appendReaction(reaction: String, userId: Long, postId: Long)
|
||||||
|
suspend fun removeReaction(userId: Long, postId: Long)
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class PostApiServiceImpl(
|
class PostApiServiceImpl(
|
||||||
private val postService: IPostService,
|
private val postService: PostService,
|
||||||
private val userRepository: IUserRepository,
|
private val userRepository: UserRepository,
|
||||||
private val postResponseQueryService: PostResponseQueryService,
|
private val postResponseQueryService: PostResponseQueryService,
|
||||||
private val reactionQueryService: ReactionQueryService,
|
private val reactionQueryService: ReactionQueryService,
|
||||||
private val reactionService: IReactionService,
|
private val reactionService: ReactionService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : IPostApiService {
|
) : PostApiService {
|
||||||
override suspend fun createPost(postForm: FormPost, userId: Long): PostResponse {
|
override suspend fun createPost(postForm: Post, userId: Long): PostResponse {
|
||||||
return transaction.transaction {
|
return transaction.transaction {
|
||||||
val createdPost = postService.createLocal(
|
val createdPost = postService.createLocal(
|
||||||
PostCreateDto(
|
PostCreateDto(
|
|
@ -8,17 +8,37 @@ import dev.usbharu.hideout.exception.UsernameAlreadyExistException
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
interface UserApiService {
|
||||||
|
suspend fun findAll(limit: Int? = 100, offset: Long = 0): List<UserResponse>
|
||||||
|
|
||||||
|
suspend fun findById(id: Long): UserResponse
|
||||||
|
|
||||||
|
suspend fun findByIds(ids: List<Long>): List<UserResponse>
|
||||||
|
|
||||||
|
suspend fun findByAcct(acct: Acct): UserResponse
|
||||||
|
|
||||||
|
suspend fun findFollowers(userId: Long): List<UserResponse>
|
||||||
|
|
||||||
|
suspend fun findFollowings(userId: Long): List<UserResponse>
|
||||||
|
|
||||||
|
suspend fun findFollowersByAcct(acct: Acct): List<UserResponse>
|
||||||
|
|
||||||
|
suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse>
|
||||||
|
|
||||||
|
suspend fun createUser(username: String, password: String): UserResponse
|
||||||
|
}
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class UserApiServiceImpl(
|
class UserApiServiceImpl(
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val followerQueryService: FollowerQueryService,
|
private val followerQueryService: FollowerQueryService,
|
||||||
private val userService: IUserService,
|
private val userService: UserService,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) : IUserApiService {
|
) : UserApiService {
|
||||||
override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> =
|
override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> =
|
||||||
userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) }
|
userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) }
|
||||||
|
|
|
@ -1,9 +1,40 @@
|
||||||
package dev.usbharu.hideout.service.api
|
package dev.usbharu.hideout.service.api
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
|
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
||||||
|
import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
|
||||||
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
|
import dev.usbharu.hideout.service.auth.JwtService
|
||||||
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
|
import dev.usbharu.hideout.service.user.UserAuthServiceImpl
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
interface UserAuthApiService {
|
interface UserAuthApiService {
|
||||||
suspend fun login(username: String, password: String): JwtToken
|
suspend fun login(username: String, password: String): JwtToken
|
||||||
suspend fun refreshToken(refreshToken: RefreshToken): JwtToken
|
suspend fun refreshToken(refreshToken: RefreshToken): JwtToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class UserAuthApiServiceImpl(
|
||||||
|
private val userAuthService: UserAuthServiceImpl,
|
||||||
|
private val userQueryService: UserQueryService,
|
||||||
|
private val jwtService: JwtService,
|
||||||
|
private val transaction: Transaction
|
||||||
|
) : UserAuthApiService {
|
||||||
|
override suspend fun login(username: String, password: String): JwtToken {
|
||||||
|
return transaction.transaction {
|
||||||
|
if (userAuthService.verifyAccount(username, password).not()) {
|
||||||
|
throw InvalidUsernameOrPasswordException()
|
||||||
|
}
|
||||||
|
val user = userQueryService.findByNameAndDomain(username, Config.configData.domain)
|
||||||
|
jwtService.createToken(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken {
|
||||||
|
return transaction.transaction {
|
||||||
|
jwtService.refreshToken(refreshToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.api
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
|
||||||
import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.service.auth.IJwtService
|
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
|
||||||
import dev.usbharu.hideout.service.user.UserAuthService
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class UserAuthApiServiceImpl(
|
|
||||||
private val userAuthService: UserAuthService,
|
|
||||||
private val userQueryService: UserQueryService,
|
|
||||||
private val jwtService: IJwtService,
|
|
||||||
private val transaction: Transaction
|
|
||||||
) : UserAuthApiService {
|
|
||||||
override suspend fun login(username: String, password: String): JwtToken {
|
|
||||||
return transaction.transaction {
|
|
||||||
if (userAuthService.verifyAccount(username, password).not()) {
|
|
||||||
throw InvalidUsernameOrPasswordException()
|
|
||||||
}
|
|
||||||
val user = userQueryService.findByNameAndDomain(username, Config.configData.domain)
|
|
||||||
jwtService.createToken(user)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken {
|
|
||||||
return transaction.transaction {
|
|
||||||
jwtService.refreshToken(refreshToken)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,20 @@
|
||||||
package dev.usbharu.hideout.service.api
|
package dev.usbharu.hideout.service.api
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
interface WebFingerApiService {
|
interface WebFingerApiService {
|
||||||
suspend fun findByNameAndDomain(name: String, domain: String): User
|
suspend fun findByNameAndDomain(name: String, domain: String): User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class WebFingerApiServiceImpl(private val transaction: Transaction, private val userQueryService: UserQueryService) :
|
||||||
|
WebFingerApiService {
|
||||||
|
override suspend fun findByNameAndDomain(name: String, domain: String): User {
|
||||||
|
return transaction.transaction {
|
||||||
|
userQueryService.findByNameAndDomain(name, domain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.api
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class WebFingerApiServiceImpl(private val transaction: Transaction, private val userQueryService: UserQueryService) :
|
|
||||||
WebFingerApiService {
|
|
||||||
override suspend fun findByNameAndDomain(name: String, domain: String): User {
|
|
||||||
return transaction.transaction {
|
|
||||||
userQueryService.findByNameAndDomain(name, domain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,33 @@
|
||||||
package dev.usbharu.hideout.service.auth
|
package dev.usbharu.hideout.service.auth
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.plugins.KtorKeyMap
|
||||||
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
|
import dev.usbharu.hideout.service.core.Transaction
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
import tech.barbero.http.message.signing.SignatureHeaderVerifier
|
||||||
|
|
||||||
interface HttpSignatureVerifyService {
|
interface HttpSignatureVerifyService {
|
||||||
fun verify(headers: Headers): Boolean
|
fun verify(headers: Headers): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class HttpSignatureVerifyServiceImpl(
|
||||||
|
private val userQueryService: UserQueryService,
|
||||||
|
private val transaction: Transaction
|
||||||
|
) : HttpSignatureVerifyService {
|
||||||
|
override fun verify(headers: Headers): Boolean {
|
||||||
|
val build = SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userQueryService, transaction)).build()
|
||||||
|
return true
|
||||||
|
// build.verify(object : HttpMessage {
|
||||||
|
// override fun headerValues(name: String?): MutableList<String> {
|
||||||
|
// return name?.let { headers.getAll(it) }?.toMutableList() ?: mutableListOf()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun addHeader(name: String?, value: String?) {
|
||||||
|
// TODO()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.auth
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.plugins.KtorKeyMap
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.service.core.Transaction
|
|
||||||
import io.ktor.http.*
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
import tech.barbero.http.message.signing.SignatureHeaderVerifier
|
|
||||||
|
|
||||||
@Single
|
|
||||||
class HttpSignatureVerifyServiceImpl(
|
|
||||||
private val userQueryService: UserQueryService,
|
|
||||||
private val transaction: Transaction
|
|
||||||
) : HttpSignatureVerifyService {
|
|
||||||
override fun verify(headers: Headers): Boolean {
|
|
||||||
val build = SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userQueryService, transaction)).build()
|
|
||||||
return true
|
|
||||||
// build.verify(object : HttpMessage {
|
|
||||||
// override fun headerValues(name: String?): MutableList<String> {
|
|
||||||
// return name?.let { headers.getAll(it) }?.toMutableList() ?: mutableListOf()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun addHeader(name: String?, value: String?) {
|
|
||||||
// TODO()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.auth
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
|
||||||
|
|
||||||
interface IJwtService {
|
|
||||||
suspend fun createToken(user: User): JwtToken
|
|
||||||
suspend fun refreshToken(refreshToken: RefreshToken): JwtToken
|
|
||||||
|
|
||||||
suspend fun revokeToken(refreshToken: RefreshToken)
|
|
||||||
suspend fun revokeToken(user: User)
|
|
||||||
suspend fun revokeAll()
|
|
||||||
}
|
|
|
@ -10,8 +10,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
||||||
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
|
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
|
||||||
import dev.usbharu.hideout.query.JwtRefreshTokenQueryService
|
import dev.usbharu.hideout.query.JwtRefreshTokenQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository
|
import dev.usbharu.hideout.repository.JwtRefreshTokenRepository
|
||||||
import dev.usbharu.hideout.service.core.IMetaService
|
import dev.usbharu.hideout.service.core.MetaService
|
||||||
import dev.usbharu.hideout.util.RsaUtil
|
import dev.usbharu.hideout.util.RsaUtil
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
@ -19,14 +19,23 @@ import java.time.Instant
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
interface JwtService {
|
||||||
|
suspend fun createToken(user: User): JwtToken
|
||||||
|
suspend fun refreshToken(refreshToken: RefreshToken): JwtToken
|
||||||
|
|
||||||
|
suspend fun revokeToken(refreshToken: RefreshToken)
|
||||||
|
suspend fun revokeToken(user: User)
|
||||||
|
suspend fun revokeAll()
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("InjectDispatcher")
|
@Suppress("InjectDispatcher")
|
||||||
@Single
|
@Single
|
||||||
class JwtServiceImpl(
|
class JwtServiceImpl(
|
||||||
private val metaService: IMetaService,
|
private val metaService: MetaService,
|
||||||
private val refreshTokenRepository: IJwtRefreshTokenRepository,
|
private val refreshTokenRepository: JwtRefreshTokenRepository,
|
||||||
private val userQueryService: UserQueryService,
|
private val userQueryService: UserQueryService,
|
||||||
private val refreshTokenQueryService: JwtRefreshTokenQueryService
|
private val refreshTokenQueryService: JwtRefreshTokenQueryService
|
||||||
) : IJwtService {
|
) : JwtService {
|
||||||
|
|
||||||
private val privateKey = runBlocking {
|
private val privateKey = runBlocking {
|
||||||
RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey)
|
RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey)
|
|
@ -3,7 +3,7 @@ package dev.usbharu.hideout.service.core
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
||||||
|
|
||||||
interface IMetaService {
|
interface MetaService {
|
||||||
suspend fun getMeta(): Meta
|
suspend fun getMeta(): Meta
|
||||||
suspend fun updateMeta(meta: Meta)
|
suspend fun updateMeta(meta: Meta)
|
||||||
suspend fun getJwtMeta(): Jwt
|
suspend fun getJwtMeta(): Jwt
|
|
@ -3,12 +3,12 @@ package dev.usbharu.hideout.service.core
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
||||||
import dev.usbharu.hideout.exception.NotInitException
|
import dev.usbharu.hideout.exception.NotInitException
|
||||||
import dev.usbharu.hideout.repository.IMetaRepository
|
import dev.usbharu.hideout.repository.MetaRepository
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class MetaServiceImpl(private val metaRepository: IMetaRepository, private val transaction: Transaction) :
|
class MetaServiceImpl(private val metaRepository: MetaRepository, private val transaction: Transaction) :
|
||||||
IMetaService {
|
MetaService {
|
||||||
override suspend fun getMeta(): Meta =
|
override suspend fun getMeta(): Meta =
|
||||||
transaction.transaction { metaRepository.get() ?: throw NotInitException("Meta is null") }
|
transaction.transaction { metaRepository.get() ?: throw NotInitException("Meta is null") }
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package dev.usbharu.hideout.service.core
|
package dev.usbharu.hideout.service.core
|
||||||
|
|
||||||
interface IServerInitialiseService {
|
interface ServerInitialiseService {
|
||||||
suspend fun init()
|
suspend fun init()
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ package dev.usbharu.hideout.service.core
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
||||||
import dev.usbharu.hideout.repository.IMetaRepository
|
import dev.usbharu.hideout.repository.MetaRepository
|
||||||
import dev.usbharu.hideout.util.ServerUtil
|
import dev.usbharu.hideout.util.ServerUtil
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
|
@ -12,10 +12,10 @@ import java.util.*
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ServerInitialiseServiceImpl(
|
class ServerInitialiseServiceImpl(
|
||||||
private val metaRepository: IMetaRepository,
|
private val metaRepository: MetaRepository,
|
||||||
private val transaction: Transaction
|
private val transaction: Transaction
|
||||||
) :
|
) :
|
||||||
IServerInitialiseService {
|
ServerInitialiseService {
|
||||||
|
|
||||||
val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java)
|
val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,6 @@ package dev.usbharu.hideout.service.post
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
|
|
||||||
interface IPostService {
|
interface PostService {
|
||||||
suspend fun createLocal(post: PostCreateDto): Post
|
suspend fun createLocal(post: PostCreateDto): Post
|
||||||
}
|
}
|
|
@ -3,18 +3,18 @@ package dev.usbharu.hideout.service.post
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||||
import dev.usbharu.hideout.exception.UserNotFoundException
|
import dev.usbharu.hideout.exception.UserNotFoundException
|
||||||
import dev.usbharu.hideout.repository.IPostRepository
|
import dev.usbharu.hideout.repository.PostRepository
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
import dev.usbharu.hideout.repository.UserRepository
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubNoteService
|
import dev.usbharu.hideout.service.ap.APNoteService
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class PostServiceImpl(
|
class PostServiceImpl(
|
||||||
private val postRepository: IPostRepository,
|
private val postRepository: PostRepository,
|
||||||
private val userRepository: IUserRepository,
|
private val userRepository: UserRepository,
|
||||||
private val activityPubNoteService: ActivityPubNoteService
|
private val apNoteService: APNoteService
|
||||||
) : IPostService {
|
) : PostService {
|
||||||
override suspend fun createLocal(post: PostCreateDto): Post {
|
override suspend fun createLocal(post: PostCreateDto): Post {
|
||||||
val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found")
|
val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found")
|
||||||
val id = postRepository.generateId()
|
val id = postRepository.generateId()
|
||||||
|
@ -29,7 +29,7 @@ class PostServiceImpl(
|
||||||
repostId = null,
|
repostId = null,
|
||||||
replyId = null
|
replyId = null
|
||||||
)
|
)
|
||||||
activityPubNoteService.createNote(createPost)
|
apNoteService.createNote(createPost)
|
||||||
return internalCreate(createPost)
|
return internalCreate(createPost)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package dev.usbharu.hideout.service.reaction
|
package dev.usbharu.hideout.service.reaction
|
||||||
|
|
||||||
interface IReactionService {
|
interface ReactionService {
|
||||||
suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long)
|
suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long)
|
||||||
suspend fun sendReaction(name: String, userId: Long, postId: Long)
|
suspend fun sendReaction(name: String, userId: Long, postId: Long)
|
||||||
suspend fun removeReaction(userId: Long, postId: Long)
|
suspend fun removeReaction(userId: Long, postId: Long)
|
|
@ -3,15 +3,15 @@ package dev.usbharu.hideout.service.reaction
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
import dev.usbharu.hideout.domain.model.hideout.entity.Reaction
|
||||||
import dev.usbharu.hideout.query.ReactionQueryService
|
import dev.usbharu.hideout.query.ReactionQueryService
|
||||||
import dev.usbharu.hideout.repository.ReactionRepository
|
import dev.usbharu.hideout.repository.ReactionRepository
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubReactionService
|
import dev.usbharu.hideout.service.ap.APReactionService
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class ReactionServiceImpl(
|
class ReactionServiceImpl(
|
||||||
private val reactionRepository: ReactionRepository,
|
private val reactionRepository: ReactionRepository,
|
||||||
private val activityPubReactionService: ActivityPubReactionService,
|
private val apReactionService: APReactionService,
|
||||||
private val reactionQueryService: ReactionQueryService
|
private val reactionQueryService: ReactionQueryService
|
||||||
) : IReactionService {
|
) : ReactionService {
|
||||||
override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) {
|
override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) {
|
||||||
if (reactionQueryService.reactionAlreadyExist(postId, userId, 0).not()) {
|
if (reactionQueryService.reactionAlreadyExist(postId, userId, 0).not()) {
|
||||||
reactionRepository.save(
|
reactionRepository.save(
|
||||||
|
@ -27,7 +27,7 @@ class ReactionServiceImpl(
|
||||||
} else {
|
} else {
|
||||||
val reaction = Reaction(reactionRepository.generateId(), 0, postId, userId)
|
val reaction = Reaction(reactionRepository.generateId(), 0, postId, userId)
|
||||||
reactionRepository.save(reaction)
|
reactionRepository.save(reaction)
|
||||||
activityPubReactionService.reaction(reaction)
|
apReactionService.reaction(reaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.user
|
|
||||||
|
|
||||||
import java.security.KeyPair
|
|
||||||
|
|
||||||
interface IUserAuthService {
|
|
||||||
fun hash(password: String): String
|
|
||||||
|
|
||||||
suspend fun usernameAlreadyUse(username: String): Boolean
|
|
||||||
|
|
||||||
suspend fun generateKeyPair(): KeyPair
|
|
||||||
|
|
||||||
suspend fun verifyAccount(username: String, password: String): Boolean
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package dev.usbharu.hideout.service.user
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
|
||||||
interface IUserService {
|
|
||||||
|
|
||||||
suspend fun usernameAlreadyUse(username: String): Boolean
|
|
||||||
|
|
||||||
suspend fun createLocalUser(user: UserCreateDto): User
|
|
||||||
|
|
||||||
suspend fun createRemoteUser(user: RemoteUserCreateDto): User
|
|
||||||
|
|
||||||
/**
|
|
||||||
* フォローリクエストを送信する
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @param followerId
|
|
||||||
* @return リクエストが成功したか
|
|
||||||
*/
|
|
||||||
suspend fun followRequest(id: Long, followerId: Long): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* フォローする
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @param followerId
|
|
||||||
*/
|
|
||||||
suspend fun follow(id: Long, followerId: Long)
|
|
||||||
|
|
||||||
suspend fun unfollow(id: Long, followerId: Long): Boolean
|
|
||||||
}
|
|
|
@ -1,53 +1,13 @@
|
||||||
package dev.usbharu.hideout.service.user
|
package dev.usbharu.hideout.service.user
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
import java.security.KeyPair
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import io.ktor.util.*
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
import java.security.*
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@Single
|
interface UserAuthService {
|
||||||
class UserAuthService(
|
fun hash(password: String): String
|
||||||
val userQueryService: UserQueryService
|
|
||||||
) : IUserAuthService {
|
|
||||||
|
|
||||||
override fun hash(password: String): String {
|
suspend fun usernameAlreadyUse(username: String): Boolean
|
||||||
val digest = sha256.digest(password.toByteArray(Charsets.UTF_8))
|
|
||||||
return hex(digest)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun usernameAlreadyUse(username: String): Boolean {
|
suspend fun generateKeyPair(): KeyPair
|
||||||
userQueryService.findByName(username)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun verifyAccount(username: String, password: String): Boolean {
|
suspend fun verifyAccount(username: String, password: String): Boolean
|
||||||
val userEntity = userQueryService.findByNameAndDomain(username, Config.configData.domain)
|
|
||||||
return userEntity.password == hash(password)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun generateKeyPair(): KeyPair {
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(keySize)
|
|
||||||
return keyPairGenerator.generateKeyPair()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val sha256: MessageDigest = MessageDigest.getInstance("SHA-256")
|
|
||||||
const val keySize = 2048
|
|
||||||
const val pemSize = 64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun PublicKey.toPem(): String {
|
|
||||||
return "-----BEGIN PUBLIC KEY-----\n" +
|
|
||||||
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthService.pemSize).joinToString("\n") +
|
|
||||||
"\n-----END PUBLIC KEY-----\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
fun PrivateKey.toPem(): String {
|
|
||||||
return "-----BEGIN PRIVATE KEY-----\n" +
|
|
||||||
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthService.pemSize).joinToString("\n") +
|
|
||||||
"\n-----END PRIVATE KEY-----\n"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package dev.usbharu.hideout.service.user
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
|
import io.ktor.util.*
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
import java.security.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class UserAuthServiceImpl(
|
||||||
|
val userQueryService: UserQueryService
|
||||||
|
) : UserAuthService {
|
||||||
|
|
||||||
|
override fun hash(password: String): String {
|
||||||
|
val digest = sha256.digest(password.toByteArray(Charsets.UTF_8))
|
||||||
|
return hex(digest)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun usernameAlreadyUse(username: String): Boolean {
|
||||||
|
userQueryService.findByName(username)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun verifyAccount(username: String, password: String): Boolean {
|
||||||
|
val userEntity = userQueryService.findByNameAndDomain(username, Config.configData.domain)
|
||||||
|
return userEntity.password == hash(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun generateKeyPair(): KeyPair {
|
||||||
|
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
||||||
|
keyPairGenerator.initialize(keySize)
|
||||||
|
return keyPairGenerator.generateKeyPair()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val sha256: MessageDigest = MessageDigest.getInstance("SHA-256")
|
||||||
|
const val keySize = 2048
|
||||||
|
const val pemSize = 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PublicKey.toPem(): String {
|
||||||
|
return "-----BEGIN PUBLIC KEY-----\n" +
|
||||||
|
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthServiceImpl.pemSize).joinToString("\n") +
|
||||||
|
"\n-----END PUBLIC KEY-----\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PrivateKey.toPem(): String {
|
||||||
|
return "-----BEGIN PRIVATE KEY-----\n" +
|
||||||
|
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthServiceImpl.pemSize).joinToString("\n") +
|
||||||
|
"\n-----END PRIVATE KEY-----\n"
|
||||||
|
}
|
|
@ -1,97 +1,34 @@
|
||||||
package dev.usbharu.hideout.service.user
|
package dev.usbharu.hideout.service.user
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import dev.usbharu.hideout.exception.UserNotFoundException
|
|
||||||
import dev.usbharu.hideout.query.FollowerQueryService
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubSendFollowService
|
|
||||||
import org.koin.core.annotation.Single
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
@Single
|
@Suppress("TooManyFunctions")
|
||||||
class UserService(
|
interface UserService {
|
||||||
private val userRepository: IUserRepository,
|
|
||||||
private val userAuthService: IUserAuthService,
|
|
||||||
private val activityPubSendFollowService: ActivityPubSendFollowService,
|
|
||||||
private val userQueryService: UserQueryService,
|
|
||||||
private val followerQueryService: FollowerQueryService
|
|
||||||
) :
|
|
||||||
IUserService {
|
|
||||||
|
|
||||||
override suspend fun usernameAlreadyUse(username: String): Boolean {
|
suspend fun usernameAlreadyUse(username: String): Boolean
|
||||||
val findByNameAndDomain = userQueryService.findByNameAndDomain(username, Config.configData.domain)
|
|
||||||
return findByNameAndDomain != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun createLocalUser(user: UserCreateDto): User {
|
suspend fun createLocalUser(user: UserCreateDto): User
|
||||||
val nextId = userRepository.nextId()
|
|
||||||
val hashedPassword = userAuthService.hash(user.password)
|
|
||||||
val keyPair = userAuthService.generateKeyPair()
|
|
||||||
val userEntity = User(
|
|
||||||
id = nextId,
|
|
||||||
name = user.name,
|
|
||||||
domain = Config.configData.domain,
|
|
||||||
screenName = user.screenName,
|
|
||||||
description = user.description,
|
|
||||||
password = hashedPassword,
|
|
||||||
inbox = "${Config.configData.url}/users/${user.name}/inbox",
|
|
||||||
outbox = "${Config.configData.url}/users/${user.name}/outbox",
|
|
||||||
url = "${Config.configData.url}/users/${user.name}",
|
|
||||||
publicKey = keyPair.public.toPem(),
|
|
||||||
privateKey = keyPair.private.toPem(),
|
|
||||||
createdAt = Instant.now()
|
|
||||||
)
|
|
||||||
return userRepository.save(userEntity)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
|
suspend fun createRemoteUser(user: RemoteUserCreateDto): User
|
||||||
val nextId = userRepository.nextId()
|
|
||||||
val userEntity = User(
|
|
||||||
id = nextId,
|
|
||||||
name = user.name,
|
|
||||||
domain = user.domain,
|
|
||||||
screenName = user.screenName,
|
|
||||||
description = user.description,
|
|
||||||
inbox = user.inbox,
|
|
||||||
outbox = user.outbox,
|
|
||||||
url = user.url,
|
|
||||||
publicKey = user.publicKey,
|
|
||||||
createdAt = Instant.now()
|
|
||||||
)
|
|
||||||
return userRepository.save(userEntity)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO APのフォロー処理を作る
|
/**
|
||||||
override suspend fun followRequest(id: Long, followerId: Long): Boolean {
|
* フォローリクエストを送信する
|
||||||
val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
|
*
|
||||||
val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.")
|
* @param id
|
||||||
return if (user.domain == Config.configData.domain) {
|
* @param followerId
|
||||||
follow(id, followerId)
|
* @return リクエストが成功したか
|
||||||
true
|
*/
|
||||||
} else {
|
suspend fun followRequest(id: Long, followerId: Long): Boolean
|
||||||
if (userRepository.findFollowRequestsById(id, followerId)) {
|
|
||||||
// do-nothing
|
|
||||||
} else {
|
|
||||||
activityPubSendFollowService.sendFollow(SendFollowDto(follower, user))
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun follow(id: Long, followerId: Long) {
|
/**
|
||||||
followerQueryService.appendFollower(id, followerId)
|
* フォローする
|
||||||
if (userRepository.findFollowRequestsById(id, followerId)) {
|
*
|
||||||
userRepository.deleteFollowRequest(id, followerId)
|
* @param id
|
||||||
}
|
* @param followerId
|
||||||
}
|
*/
|
||||||
|
suspend fun follow(id: Long, followerId: Long)
|
||||||
|
|
||||||
override suspend fun unfollow(id: Long, followerId: Long): Boolean {
|
suspend fun unfollow(id: Long, followerId: Long): Boolean
|
||||||
followerQueryService.removeFollower(id, followerId)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
package dev.usbharu.hideout.service.user
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.config.Config
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
|
import dev.usbharu.hideout.exception.UserNotFoundException
|
||||||
|
import dev.usbharu.hideout.query.FollowerQueryService
|
||||||
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
|
import dev.usbharu.hideout.repository.UserRepository
|
||||||
|
import dev.usbharu.hideout.service.ap.APSendFollowService
|
||||||
|
import org.koin.core.annotation.Single
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@Single
|
||||||
|
class UserServiceImpl(
|
||||||
|
private val userRepository: UserRepository,
|
||||||
|
private val userAuthService: UserAuthService,
|
||||||
|
private val apSendFollowService: APSendFollowService,
|
||||||
|
private val userQueryService: UserQueryService,
|
||||||
|
private val followerQueryService: FollowerQueryService
|
||||||
|
) :
|
||||||
|
UserService {
|
||||||
|
|
||||||
|
override suspend fun usernameAlreadyUse(username: String): Boolean {
|
||||||
|
val findByNameAndDomain = userQueryService.findByNameAndDomain(username, Config.configData.domain)
|
||||||
|
return findByNameAndDomain != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun createLocalUser(user: UserCreateDto): User {
|
||||||
|
val nextId = userRepository.nextId()
|
||||||
|
val hashedPassword = userAuthService.hash(user.password)
|
||||||
|
val keyPair = userAuthService.generateKeyPair()
|
||||||
|
val userEntity = User(
|
||||||
|
id = nextId,
|
||||||
|
name = user.name,
|
||||||
|
domain = Config.configData.domain,
|
||||||
|
screenName = user.screenName,
|
||||||
|
description = user.description,
|
||||||
|
password = hashedPassword,
|
||||||
|
inbox = "${Config.configData.url}/users/${user.name}/inbox",
|
||||||
|
outbox = "${Config.configData.url}/users/${user.name}/outbox",
|
||||||
|
url = "${Config.configData.url}/users/${user.name}",
|
||||||
|
publicKey = keyPair.public.toPem(),
|
||||||
|
privateKey = keyPair.private.toPem(),
|
||||||
|
createdAt = Instant.now()
|
||||||
|
)
|
||||||
|
return userRepository.save(userEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
|
||||||
|
val nextId = userRepository.nextId()
|
||||||
|
val userEntity = User(
|
||||||
|
id = nextId,
|
||||||
|
name = user.name,
|
||||||
|
domain = user.domain,
|
||||||
|
screenName = user.screenName,
|
||||||
|
description = user.description,
|
||||||
|
inbox = user.inbox,
|
||||||
|
outbox = user.outbox,
|
||||||
|
url = user.url,
|
||||||
|
publicKey = user.publicKey,
|
||||||
|
createdAt = Instant.now()
|
||||||
|
)
|
||||||
|
return userRepository.save(userEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO APのフォロー処理を作る
|
||||||
|
override suspend fun followRequest(id: Long, followerId: Long): Boolean {
|
||||||
|
val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
|
||||||
|
val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.")
|
||||||
|
return if (user.domain == Config.configData.domain) {
|
||||||
|
follow(id, followerId)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
if (userRepository.findFollowRequestsById(id, followerId)) {
|
||||||
|
// do-nothing
|
||||||
|
} else {
|
||||||
|
apSendFollowService.sendFollow(SendFollowDto(follower, user))
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun follow(id: Long, followerId: Long) {
|
||||||
|
followerQueryService.appendFollower(id, followerId)
|
||||||
|
if (userRepository.findFollowRequestsById(id, followerId)) {
|
||||||
|
userRepository.deleteFollowRequest(id, followerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun unfollow(id: Long, followerId: Long): Boolean {
|
||||||
|
followerQueryService.removeFollower(id, followerId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,9 +18,9 @@ import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.routing.api.internal.v1.auth
|
import dev.usbharu.hideout.routing.api.internal.v1.auth
|
||||||
import dev.usbharu.hideout.service.api.UserAuthApiService
|
import dev.usbharu.hideout.service.api.UserAuthApiService
|
||||||
import dev.usbharu.hideout.service.auth.IJwtService
|
import dev.usbharu.hideout.service.auth.JwtService
|
||||||
import dev.usbharu.hideout.service.core.IMetaService
|
import dev.usbharu.hideout.service.core.MetaService
|
||||||
import dev.usbharu.hideout.service.user.IUserAuthService
|
import dev.usbharu.hideout.service.user.UserAuthService
|
||||||
import dev.usbharu.hideout.util.Base64Util
|
import dev.usbharu.hideout.util.Base64Util
|
||||||
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
|
@ -51,7 +51,7 @@ class SecurityKtTest {
|
||||||
val userAuthService = mock<UserAuthApiService> {
|
val userAuthService = mock<UserAuthApiService> {
|
||||||
onBlocking { login(eq("testUser"), eq("password")) } doReturn jwtToken
|
onBlocking { login(eq("testUser"), eq("password")) } doReturn jwtToken
|
||||||
}
|
}
|
||||||
val metaService = mock<IMetaService>()
|
val metaService = mock<MetaService>()
|
||||||
val userQueryService = mock<UserQueryService> {
|
val userQueryService = mock<UserQueryService> {
|
||||||
onBlocking { findByNameAndDomain(eq("testUser"), eq("example.com")) } doReturn User(
|
onBlocking { findByNameAndDomain(eq("testUser"), eq("example.com")) } doReturn User(
|
||||||
id = 1L,
|
id = 1L,
|
||||||
|
@ -93,12 +93,12 @@ class SecurityKtTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
||||||
mock<IUserAuthService> {
|
mock<UserAuthService> {
|
||||||
onBlocking { verifyAccount(anyString(), anyString()) }.doReturn(false)
|
onBlocking { verifyAccount(anyString(), anyString()) }.doReturn(false)
|
||||||
}
|
}
|
||||||
val metaService = mock<IMetaService>()
|
val metaService = mock<MetaService>()
|
||||||
mock<UserQueryService>()
|
mock<UserQueryService>()
|
||||||
mock<IJwtService>()
|
mock<JwtService>()
|
||||||
val jwkProvider = mock<JwkProvider>()
|
val jwkProvider = mock<JwkProvider>()
|
||||||
val userAuthApiService = mock<UserAuthApiService> {
|
val userAuthApiService = mock<UserAuthApiService> {
|
||||||
onBlocking { login(anyString(), anyString()) } doThrow InvalidUsernameOrPasswordException()
|
onBlocking { login(anyString(), anyString()) } doThrow InvalidUsernameOrPasswordException()
|
||||||
|
@ -126,7 +126,7 @@ class SecurityKtTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
||||||
val metaService = mock<IMetaService>()
|
val metaService = mock<MetaService>()
|
||||||
val jwkProvider = mock<JwkProvider>()
|
val jwkProvider = mock<JwkProvider>()
|
||||||
val userAuthApiService = mock<UserAuthApiService> {
|
val userAuthApiService = mock<UserAuthApiService> {
|
||||||
onBlocking { login(anyString(), eq("InvalidPassword")) } doThrow InvalidUsernameOrPasswordException()
|
onBlocking { login(anyString(), eq("InvalidPassword")) } doThrow InvalidUsernameOrPasswordException()
|
||||||
|
@ -247,7 +247,7 @@ class SecurityKtTest {
|
||||||
.withClaim("uid", 123456L)
|
.withClaim("uid", 123456L)
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
onBlocking { getJwtMeta() }.doReturn(
|
||||||
Jwt(
|
Jwt(
|
||||||
kid,
|
kid,
|
||||||
|
@ -308,7 +308,7 @@ class SecurityKtTest {
|
||||||
.withClaim("uid", 123345L)
|
.withClaim("uid", 123345L)
|
||||||
.withExpiresAt(now.minus(30, ChronoUnit.MINUTES))
|
.withExpiresAt(now.minus(30, ChronoUnit.MINUTES))
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
onBlocking { getJwtMeta() }.doReturn(
|
||||||
Jwt(
|
Jwt(
|
||||||
kid,
|
kid,
|
||||||
|
@ -367,7 +367,7 @@ class SecurityKtTest {
|
||||||
.withClaim("uid", 12345L)
|
.withClaim("uid", 12345L)
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
onBlocking { getJwtMeta() }.doReturn(
|
||||||
Jwt(
|
Jwt(
|
||||||
kid,
|
kid,
|
||||||
|
@ -426,7 +426,7 @@ class SecurityKtTest {
|
||||||
.withClaim("uid", null as Long?)
|
.withClaim("uid", null as Long?)
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
onBlocking { getJwtMeta() }.doReturn(
|
||||||
Jwt(
|
Jwt(
|
||||||
kid,
|
kid,
|
||||||
|
@ -484,7 +484,7 @@ class SecurityKtTest {
|
||||||
.withKeyId(kid.toString())
|
.withKeyId(kid.toString())
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
onBlocking { getJwtMeta() }.doReturn(
|
||||||
Jwt(
|
Jwt(
|
||||||
kid,
|
kid,
|
||||||
|
|
|
@ -3,10 +3,10 @@ package dev.usbharu.hideout.routing.activitypub
|
||||||
import dev.usbharu.hideout.exception.JsonParseException
|
import dev.usbharu.hideout.exception.JsonParseException
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
import dev.usbharu.hideout.plugins.configureSerialization
|
||||||
import dev.usbharu.hideout.plugins.configureStatusPages
|
import dev.usbharu.hideout.plugins.configureStatusPages
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubService
|
import dev.usbharu.hideout.service.ap.APService
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
import dev.usbharu.hideout.service.ap.APUserService
|
||||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.config.*
|
import io.ktor.server.config.*
|
||||||
|
@ -44,16 +44,16 @@ class InboxRoutingKtTest {
|
||||||
val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {
|
val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {
|
||||||
on { verify(any()) } doReturn true
|
on { verify(any()) } doReturn true
|
||||||
}
|
}
|
||||||
val activityPubService = mock<ActivityPubService> {
|
val apService = mock<APService> {
|
||||||
on { parseActivity(any()) } doThrow JsonParseException()
|
on { parseActivity(any()) } doThrow JsonParseException()
|
||||||
}
|
}
|
||||||
mock<IUserService>()
|
mock<UserService>()
|
||||||
mock<ActivityPubUserService>()
|
mock<APUserService>()
|
||||||
application {
|
application {
|
||||||
configureStatusPages()
|
configureStatusPages()
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
routing {
|
routing {
|
||||||
inbox(httpSignatureVerifyService, activityPubService)
|
inbox(httpSignatureVerifyService, apService)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.post("/inbox").let {
|
client.post("/inbox").let {
|
||||||
|
@ -85,16 +85,16 @@ class InboxRoutingKtTest {
|
||||||
val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {
|
val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {
|
||||||
on { verify(any()) } doReturn true
|
on { verify(any()) } doReturn true
|
||||||
}
|
}
|
||||||
val activityPubService = mock<ActivityPubService> {
|
val apService = mock<APService> {
|
||||||
on { parseActivity(any()) } doThrow JsonParseException()
|
on { parseActivity(any()) } doThrow JsonParseException()
|
||||||
}
|
}
|
||||||
mock<IUserService>()
|
mock<UserService>()
|
||||||
mock<ActivityPubUserService>()
|
mock<APUserService>()
|
||||||
application {
|
application {
|
||||||
configureStatusPages()
|
configureStatusPages()
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
routing {
|
routing {
|
||||||
inbox(httpSignatureVerifyService, activityPubService)
|
inbox(httpSignatureVerifyService, apService)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.post("/users/test/inbox").let {
|
client.post("/users/test/inbox").let {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import dev.usbharu.hideout.domain.model.ap.Person
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
import dev.usbharu.hideout.plugins.configureSerialization
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
import dev.usbharu.hideout.service.ap.APUserService
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
import dev.usbharu.hideout.util.HttpUtil.Activity
|
||||||
import dev.usbharu.hideout.util.HttpUtil.JsonLd
|
import dev.usbharu.hideout.util.HttpUtil.JsonLd
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
|
@ -63,14 +63,14 @@ class UsersAPTest {
|
||||||
)
|
)
|
||||||
person.context = listOf("https://www.w3.org/ns/activitystreams")
|
person.context = listOf("https://www.w3.org/ns/activitystreams")
|
||||||
|
|
||||||
val activityPubUserService = mock<ActivityPubUserService> {
|
val apUserService = mock<APUserService> {
|
||||||
onBlocking { getPersonByName(anyString()) } doReturn person
|
onBlocking { getPersonByName(anyString()) } doReturn person
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
routing {
|
routing {
|
||||||
usersAP(activityPubUserService, mock(), mock(), TestTransaction)
|
usersAP(apUserService, mock(), mock(), TestTransaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.get("/users/test") {
|
client.get("/users/test") {
|
||||||
|
@ -121,14 +121,14 @@ class UsersAPTest {
|
||||||
)
|
)
|
||||||
person.context = listOf("https://www.w3.org/ns/activitystreams")
|
person.context = listOf("https://www.w3.org/ns/activitystreams")
|
||||||
|
|
||||||
val activityPubUserService = mock<ActivityPubUserService> {
|
val apUserService = mock<APUserService> {
|
||||||
onBlocking { getPersonByName(anyString()) } doReturn person
|
onBlocking { getPersonByName(anyString()) } doReturn person
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
configureSerialization()
|
configureSerialization()
|
||||||
routing {
|
routing {
|
||||||
usersAP(activityPubUserService, mock(), mock(), TestTransaction)
|
usersAP(apUserService, mock(), mock(), TestTransaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.get("/users/test") {
|
client.get("/users/test") {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
import dev.usbharu.hideout.plugins.configureSecurity
|
import dev.usbharu.hideout.plugins.configureSecurity
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
import dev.usbharu.hideout.plugins.configureSerialization
|
||||||
import dev.usbharu.hideout.service.api.IPostApiService
|
import dev.usbharu.hideout.service.api.PostApiService
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.statement.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
@ -60,7 +60,7 @@ class PostsTest {
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getAll(
|
getAll(
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
|
@ -135,7 +135,7 @@ class PostsTest {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getAll(
|
getAll(
|
||||||
since = anyOrNull(),
|
since = anyOrNull(),
|
||||||
|
@ -191,7 +191,7 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { getById(any(), anyOrNull()) } doReturn post
|
onBlocking { getById(any(), anyOrNull()) } doReturn post
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -230,7 +230,7 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/1"
|
url = "https://example.com/posts/1"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { getById(any(), isNotNull()) } doReturn post
|
onBlocking { getById(any(), isNotNull()) } doReturn post
|
||||||
}
|
}
|
||||||
val claim = mock<Claim> {
|
val claim = mock<Claim> {
|
||||||
|
@ -273,7 +273,7 @@ class PostsTest {
|
||||||
val payload = mock<Payload> {
|
val payload = mock<Payload> {
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
}
|
}
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { createPost(any(), any()) } doAnswer {
|
onBlocking { createPost(any(), any()) } doAnswer {
|
||||||
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
||||||
val userId = it.getArgument<Long>(1)
|
val userId = it.getArgument<Long>(1)
|
||||||
|
@ -360,7 +360,7 @@ class PostsTest {
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = any(),
|
nameOrId = any(),
|
||||||
|
@ -421,7 +421,7 @@ class PostsTest {
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = eq("test1"),
|
nameOrId = eq("test1"),
|
||||||
|
@ -482,7 +482,7 @@ class PostsTest {
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = eq("test1@example.com"),
|
nameOrId = eq("test1@example.com"),
|
||||||
|
@ -543,7 +543,7 @@ class PostsTest {
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking {
|
onBlocking {
|
||||||
getByUser(
|
getByUser(
|
||||||
nameOrId = eq("@test1@example.com"),
|
nameOrId = eq("@test1@example.com"),
|
||||||
|
@ -593,7 +593,7 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -633,7 +633,7 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -673,7 +673,7 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -713,7 +713,7 @@ class PostsTest {
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
createdAt = Instant.now().toEpochMilli(),
|
||||||
url = "https://example.com/posts/2"
|
url = "https://example.com/posts/2"
|
||||||
)
|
)
|
||||||
val postService = mock<IPostApiService> {
|
val postService = mock<PostApiService> {
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
|
|
@ -10,8 +10,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||||
import dev.usbharu.hideout.plugins.configureSecurity
|
import dev.usbharu.hideout.plugins.configureSecurity
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
import dev.usbharu.hideout.plugins.configureSerialization
|
||||||
import dev.usbharu.hideout.service.api.IUserApiService
|
import dev.usbharu.hideout.service.api.UserApiService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.statement.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
|
@ -53,7 +53,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
val userService = mock<IUserApiService> {
|
val userService = mock<UserApiService> {
|
||||||
onBlocking { findAll(anyOrNull(), anyOrNull()) } doReturn users
|
onBlocking { findAll(anyOrNull(), anyOrNull()) } doReturn users
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -77,7 +77,7 @@ class UsersTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val userCreateDto = UserCreate("test", "XXXXXXX")
|
val userCreateDto = UserCreate("test", "XXXXXXX")
|
||||||
val userService = mock<IUserService> {
|
val userService = mock<UserService> {
|
||||||
onBlocking { usernameAlreadyUse(any()) } doReturn false
|
onBlocking { usernameAlreadyUse(any()) } doReturn false
|
||||||
onBlocking { createLocalUser(any()) } doReturn User(
|
onBlocking { createLocalUser(any()) } doReturn User(
|
||||||
id = 12345,
|
id = 12345,
|
||||||
|
@ -122,7 +122,7 @@ class UsersTest {
|
||||||
config = ApplicationConfig("empty.conf")
|
config = ApplicationConfig("empty.conf")
|
||||||
}
|
}
|
||||||
val userCreateDto = UserCreate("test", "XXXXXXX")
|
val userCreateDto = UserCreate("test", "XXXXXXX")
|
||||||
val userService = mock<IUserService> {
|
val userService = mock<UserService> {
|
||||||
onBlocking { usernameAlreadyUse(any()) } doReturn true
|
onBlocking { usernameAlreadyUse(any()) } doReturn true
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -157,7 +157,7 @@ class UsersTest {
|
||||||
"https://example.com/test",
|
"https://example.com/test",
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findByAcct(any()) } doReturn userResponse
|
onBlocking { findByAcct(any()) } doReturn userResponse
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -190,7 +190,7 @@ class UsersTest {
|
||||||
"https://example.com/test",
|
"https://example.com/test",
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findById(any()) } doReturn userResponse
|
onBlocking { findById(any()) } doReturn userResponse
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -223,7 +223,7 @@ class UsersTest {
|
||||||
"https://example.com/test",
|
"https://example.com/test",
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findByAcct(any()) } doReturn userResponse
|
onBlocking { findByAcct(any()) } doReturn userResponse
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -256,7 +256,7 @@ class UsersTest {
|
||||||
"https://example.com/test",
|
"https://example.com/test",
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findByAcct(any()) } doReturn userResponse
|
onBlocking { findByAcct(any()) } doReturn userResponse
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -301,7 +301,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findFollowersByAcct(any()) } doReturn followers
|
onBlocking { findFollowersByAcct(any()) } doReturn followers
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -346,7 +346,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findFollowersByAcct(any()) } doReturn followers
|
onBlocking { findFollowersByAcct(any()) } doReturn followers
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -391,7 +391,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findFollowers(any()) } doReturn followers
|
onBlocking { findFollowers(any()) } doReturn followers
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -423,7 +423,7 @@ class UsersTest {
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
}
|
}
|
||||||
|
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findByAcct(any()) } doReturn UserResponse(
|
onBlocking { findByAcct(any()) } doReturn UserResponse(
|
||||||
"1235",
|
"1235",
|
||||||
"follower1",
|
"follower1",
|
||||||
|
@ -434,7 +434,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userService = mock<IUserService> {
|
val userService = mock<UserService> {
|
||||||
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn true
|
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn true
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -473,7 +473,7 @@ class UsersTest {
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
}
|
}
|
||||||
|
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findByAcct(any()) } doReturn UserResponse(
|
onBlocking { findByAcct(any()) } doReturn UserResponse(
|
||||||
"1235",
|
"1235",
|
||||||
"follower1",
|
"follower1",
|
||||||
|
@ -484,7 +484,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userService = mock<IUserService> {
|
val userService = mock<UserService> {
|
||||||
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false
|
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -523,7 +523,7 @@ class UsersTest {
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
on { getClaim(eq("uid")) } doReturn claim
|
||||||
}
|
}
|
||||||
|
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findById(any()) } doReturn UserResponse(
|
onBlocking { findById(any()) } doReturn UserResponse(
|
||||||
"1235",
|
"1235",
|
||||||
"follower1",
|
"follower1",
|
||||||
|
@ -534,7 +534,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val userService = mock<IUserService> {
|
val userService = mock<UserService> {
|
||||||
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false
|
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -586,7 +586,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findFollowingsByAcct(any()) } doReturn followers
|
onBlocking { findFollowingsByAcct(any()) } doReturn followers
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -631,7 +631,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findFollowingsByAcct(any()) } doReturn followers
|
onBlocking { findFollowingsByAcct(any()) } doReturn followers
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
@ -676,7 +676,7 @@ class UsersTest {
|
||||||
Instant.now().toEpochMilli()
|
Instant.now().toEpochMilli()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val userApiService = mock<IUserApiService> {
|
val userApiService = mock<UserApiService> {
|
||||||
onBlocking { findFollowings(any()) } doReturn followers
|
onBlocking { findFollowings(any()) } doReturn followers
|
||||||
}
|
}
|
||||||
application {
|
application {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.config.ConfigData
|
import dev.usbharu.hideout.config.ConfigData
|
||||||
|
@ -25,7 +25,7 @@ import utils.JsonObjectMapper
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class ActivityPubNoteServiceImplTest {
|
class APNoteServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `createPost 新しい投稿`() = runTest {
|
fun `createPost 新しい投稿`() = runTest {
|
||||||
val followers = listOf<User>(
|
val followers = listOf<User>(
|
||||||
|
@ -76,7 +76,7 @@ class ActivityPubNoteServiceImplTest {
|
||||||
}
|
}
|
||||||
val jobQueueParentService = mock<JobQueueParentService>()
|
val jobQueueParentService = mock<JobQueueParentService>()
|
||||||
val activityPubNoteService =
|
val activityPubNoteService =
|
||||||
ActivityPubNoteServiceImpl(
|
APNoteServiceImpl(
|
||||||
mock(),
|
mock(),
|
||||||
jobQueueParentService,
|
jobQueueParentService,
|
||||||
mock(),
|
mock(),
|
||||||
|
@ -107,7 +107,7 @@ class ActivityPubNoteServiceImplTest {
|
||||||
respondOk()
|
respondOk()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val activityPubNoteService = ActivityPubNoteServiceImpl(
|
val activityPubNoteService = APNoteServiceImpl(
|
||||||
httpClient,
|
httpClient,
|
||||||
mock(),
|
mock(),
|
||||||
mock(),
|
mock(),
|
|
@ -1,7 +1,7 @@
|
||||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
|
||||||
package dev.usbharu.hideout.service.activitypub
|
package dev.usbharu.hideout.service.ap
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import dev.usbharu.hideout.config.Config
|
import dev.usbharu.hideout.config.Config
|
||||||
|
@ -11,7 +11,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.User
|
||||||
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
|
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||||
import dev.usbharu.hideout.service.user.IUserService
|
import dev.usbharu.hideout.service.user.UserService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.engine.mock.*
|
import io.ktor.client.engine.mock.*
|
||||||
import kjob.core.dsl.ScheduleContext
|
import kjob.core.dsl.ScheduleContext
|
||||||
|
@ -27,14 +27,14 @@ import utils.JsonObjectMapper
|
||||||
import utils.TestTransaction
|
import utils.TestTransaction
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
class ActivityPubReceiveFollowServiceImplTest {
|
class APReceiveFollowServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `receiveFollow フォロー受付処理`() = runTest {
|
fun `receiveFollow フォロー受付処理`() = runTest {
|
||||||
val jobQueueParentService = mock<JobQueueParentService> {
|
val jobQueueParentService = mock<JobQueueParentService> {
|
||||||
onBlocking { schedule(eq(ReceiveFollowJob), any()) } doReturn Unit
|
onBlocking { schedule(eq(ReceiveFollowJob), any()) } doReturn Unit
|
||||||
}
|
}
|
||||||
val activityPubFollowService =
|
val activityPubFollowService =
|
||||||
ActivityPubReceiveFollowServiceImpl(jobQueueParentService, mock(), mock(), mock(), mock(), TestTransaction)
|
APReceiveFollowServiceImpl(jobQueueParentService, mock(), mock(), mock(), mock(), TestTransaction)
|
||||||
activityPubFollowService.receiveFollow(
|
activityPubFollowService.receiveFollow(
|
||||||
Follow(
|
Follow(
|
||||||
emptyList(),
|
emptyList(),
|
||||||
|
@ -96,7 +96,7 @@ class ActivityPubReceiveFollowServiceImplTest {
|
||||||
)
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
val activityPubUserService = mock<ActivityPubUserService> {
|
val apUserService = mock<APUserService> {
|
||||||
onBlocking { fetchPerson(anyString(), any()) } doReturn person
|
onBlocking { fetchPerson(anyString(), any()) } doReturn person
|
||||||
}
|
}
|
||||||
val userQueryService = mock<UserQueryService> {
|
val userQueryService = mock<UserQueryService> {
|
||||||
|
@ -128,13 +128,13 @@ class ActivityPubReceiveFollowServiceImplTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val userService = mock<IUserService> {
|
val userService = mock<UserService> {
|
||||||
onBlocking { followRequest(any(), any()) } doReturn false
|
onBlocking { followRequest(any(), any()) } doReturn false
|
||||||
}
|
}
|
||||||
val activityPubFollowService =
|
val activityPubFollowService =
|
||||||
ActivityPubReceiveFollowServiceImpl(
|
APReceiveFollowServiceImpl(
|
||||||
mock(),
|
mock(),
|
||||||
activityPubUserService,
|
apUserService,
|
||||||
userService,
|
userService,
|
||||||
HttpClient(
|
HttpClient(
|
||||||
MockEngine { httpRequestData ->
|
MockEngine { httpRequestData ->
|
|
@ -14,8 +14,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
|
||||||
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
|
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
|
||||||
import dev.usbharu.hideout.query.JwtRefreshTokenQueryService
|
import dev.usbharu.hideout.query.JwtRefreshTokenQueryService
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
import dev.usbharu.hideout.query.UserQueryService
|
||||||
import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository
|
import dev.usbharu.hideout.repository.JwtRefreshTokenRepository
|
||||||
import dev.usbharu.hideout.service.core.IMetaService
|
import dev.usbharu.hideout.service.core.MetaService
|
||||||
import dev.usbharu.hideout.util.Base64Util
|
import dev.usbharu.hideout.util.Base64Util
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -42,14 +42,14 @@ class JwtServiceImplTest {
|
||||||
keyPairGenerator.initialize(2048)
|
keyPairGenerator.initialize(2048)
|
||||||
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
||||||
|
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() } doReturn Jwt(
|
onBlocking { getJwtMeta() } doReturn Jwt(
|
||||||
kid,
|
kid,
|
||||||
Base64Util.encode(generateKeyPair.private.encoded),
|
Base64Util.encode(generateKeyPair.private.encoded),
|
||||||
Base64Util.encode(generateKeyPair.public.encoded)
|
Base64Util.encode(generateKeyPair.public.encoded)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> {
|
val refreshTokenRepository = mock<JwtRefreshTokenRepository> {
|
||||||
onBlocking { generateId() } doReturn 1L
|
onBlocking { generateId() } doReturn 1L
|
||||||
}
|
}
|
||||||
val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock(), mock())
|
val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock(), mock())
|
||||||
|
@ -94,7 +94,7 @@ class JwtServiceImplTest {
|
||||||
keyPairGenerator.initialize(2048)
|
keyPairGenerator.initialize(2048)
|
||||||
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
||||||
|
|
||||||
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> {
|
val refreshTokenRepository = mock<JwtRefreshTokenRepository> {
|
||||||
onBlocking { generateId() } doReturn 2L
|
onBlocking { generateId() } doReturn 2L
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class JwtServiceImplTest {
|
||||||
createdAt = Instant.now()
|
createdAt = Instant.now()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() } doReturn Jwt(
|
onBlocking { getJwtMeta() } doReturn Jwt(
|
||||||
kid,
|
kid,
|
||||||
Base64Util.encode(generateKeyPair.private.encoded),
|
Base64Util.encode(generateKeyPair.private.encoded),
|
||||||
|
@ -160,7 +160,7 @@ class JwtServiceImplTest {
|
||||||
keyPairGenerator.initialize(2048)
|
keyPairGenerator.initialize(2048)
|
||||||
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
||||||
|
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() } doReturn Jwt(
|
onBlocking { getJwtMeta() } doReturn Jwt(
|
||||||
kid,
|
kid,
|
||||||
Base64Util.encode(generateKeyPair.private.encoded),
|
Base64Util.encode(generateKeyPair.private.encoded),
|
||||||
|
@ -187,7 +187,7 @@ class JwtServiceImplTest {
|
||||||
keyPairGenerator.initialize(2048)
|
keyPairGenerator.initialize(2048)
|
||||||
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
||||||
|
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() } doReturn Jwt(
|
onBlocking { getJwtMeta() } doReturn Jwt(
|
||||||
kid,
|
kid,
|
||||||
Base64Util.encode(generateKeyPair.private.encoded),
|
Base64Util.encode(generateKeyPair.private.encoded),
|
||||||
|
@ -214,7 +214,7 @@ class JwtServiceImplTest {
|
||||||
keyPairGenerator.initialize(2048)
|
keyPairGenerator.initialize(2048)
|
||||||
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
val generateKeyPair = keyPairGenerator.generateKeyPair()
|
||||||
|
|
||||||
val metaService = mock<IMetaService> {
|
val metaService = mock<MetaService> {
|
||||||
onBlocking { getJwtMeta() } doReturn Jwt(
|
onBlocking { getJwtMeta() } doReturn Jwt(
|
||||||
kid,
|
kid,
|
||||||
Base64Util.encode(generateKeyPair.private.encoded),
|
Base64Util.encode(generateKeyPair.private.encoded),
|
||||||
|
|
|
@ -5,7 +5,7 @@ package dev.usbharu.hideout.service.core
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
||||||
import dev.usbharu.hideout.exception.NotInitException
|
import dev.usbharu.hideout.exception.NotInitException
|
||||||
import dev.usbharu.hideout.repository.IMetaRepository
|
import dev.usbharu.hideout.repository.MetaRepository
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
@ -19,7 +19,7 @@ class MetaServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `getMeta メタデータを取得できる`() = runTest {
|
fun `getMeta メタデータを取得できる`() = runTest {
|
||||||
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
|
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn meta
|
onBlocking { get() } doReturn meta
|
||||||
}
|
}
|
||||||
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
||||||
|
@ -29,7 +29,7 @@ class MetaServiceImplTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest {
|
fun `getMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest {
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn null
|
onBlocking { get() } doReturn null
|
||||||
}
|
}
|
||||||
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
||||||
|
@ -39,7 +39,7 @@ class MetaServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `updateMeta メタデータを保存できる`() = runTest {
|
fun `updateMeta メタデータを保存できる`() = runTest {
|
||||||
val meta = Meta("1.0.1", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
|
val meta = Meta("1.0.1", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { save(any()) } doReturn Unit
|
onBlocking { save(any()) } doReturn Unit
|
||||||
}
|
}
|
||||||
val metaServiceImpl = MetaServiceImpl(metaRepository, TestTransaction)
|
val metaServiceImpl = MetaServiceImpl(metaRepository, TestTransaction)
|
||||||
|
@ -53,7 +53,7 @@ class MetaServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `getJwtMeta Jwtメタデータを取得できる`() = runTest {
|
fun `getJwtMeta Jwtメタデータを取得できる`() = runTest {
|
||||||
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
|
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn meta
|
onBlocking { get() } doReturn meta
|
||||||
}
|
}
|
||||||
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
||||||
|
@ -63,7 +63,7 @@ class MetaServiceImplTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getJwtMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest {
|
fun `getJwtMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest {
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn null
|
onBlocking { get() } doReturn null
|
||||||
}
|
}
|
||||||
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
val metaService = MetaServiceImpl(metaRepository, TestTransaction)
|
||||||
|
|
|
@ -4,7 +4,7 @@ package dev.usbharu.hideout.service.core
|
||||||
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
import dev.usbharu.hideout.domain.model.hideout.entity.Meta
|
||||||
import dev.usbharu.hideout.repository.IMetaRepository
|
import dev.usbharu.hideout.repository.MetaRepository
|
||||||
import dev.usbharu.hideout.util.ServerUtil
|
import dev.usbharu.hideout.util.ServerUtil
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -17,7 +17,7 @@ import kotlin.test.assertEquals
|
||||||
class ServerInitialiseServiceImplTest {
|
class ServerInitialiseServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `init メタデータが無いときに初期化を実行する`() = runTest {
|
fun `init メタデータが無いときに初期化を実行する`() = runTest {
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn null
|
onBlocking { get() } doReturn null
|
||||||
onBlocking { save(any()) } doReturn Unit
|
onBlocking { save(any()) } doReturn Unit
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class ServerInitialiseServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `init メタデータが存在して同じバージョンのときは何もしない`() = runTest {
|
fun `init メタデータが存在して同じバージョンのときは何もしない`() = runTest {
|
||||||
val meta = Meta(ServerUtil.getImplementationVersion(), Jwt(UUID.randomUUID(), "aaafafd", "afafasdf"))
|
val meta = Meta(ServerUtil.getImplementationVersion(), Jwt(UUID.randomUUID(), "aaafafd", "afafasdf"))
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn meta
|
onBlocking { get() } doReturn meta
|
||||||
}
|
}
|
||||||
val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository, TestTransaction)
|
val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository, TestTransaction)
|
||||||
|
@ -41,7 +41,7 @@ class ServerInitialiseServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
fun `init メタデータが存在して違うバージョンのときはバージョンを変更する`() = runTest {
|
fun `init メタデータが存在して違うバージョンのときはバージョンを変更する`() = runTest {
|
||||||
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "aaafafd", "afafasdf"))
|
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "aaafafd", "afafasdf"))
|
||||||
val metaRepository = mock<IMetaRepository> {
|
val metaRepository = mock<MetaRepository> {
|
||||||
onBlocking { get() } doReturn meta
|
onBlocking { get() } doReturn meta
|
||||||
onBlocking { save(any()) } doReturn Unit
|
onBlocking { save(any()) } doReturn Unit
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import dev.usbharu.hideout.config.Config
|
||||||
import dev.usbharu.hideout.config.ConfigData
|
import dev.usbharu.hideout.config.ConfigData
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
|
||||||
import dev.usbharu.hideout.repository.IUserRepository
|
import dev.usbharu.hideout.repository.UserRepository
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
@ -20,15 +20,15 @@ class UserServiceTest {
|
||||||
@Test
|
@Test
|
||||||
fun `createLocalUser ローカルユーザーを作成できる`() = runTest {
|
fun `createLocalUser ローカルユーザーを作成できる`() = runTest {
|
||||||
Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
|
Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
|
||||||
val userRepository = mock<IUserRepository> {
|
val userRepository = mock<UserRepository> {
|
||||||
onBlocking { nextId() } doReturn 110001L
|
onBlocking { nextId() } doReturn 110001L
|
||||||
}
|
}
|
||||||
val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair()
|
val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair()
|
||||||
val userAuthService = mock<IUserAuthService> {
|
val userAuthService = mock<UserAuthService> {
|
||||||
onBlocking { hash(anyString()) } doReturn "hashedPassword"
|
onBlocking { hash(anyString()) } doReturn "hashedPassword"
|
||||||
onBlocking { generateKeyPair() } doReturn generateKeyPair
|
onBlocking { generateKeyPair() } doReturn generateKeyPair
|
||||||
}
|
}
|
||||||
val userService = UserService(userRepository, userAuthService, mock(), mock(), mock())
|
val userService = UserServiceImpl(userRepository, userAuthService, mock(), mock(), mock())
|
||||||
userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test"))
|
userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test"))
|
||||||
verify(userRepository, times(1)).save(any())
|
verify(userRepository, times(1)).save(any())
|
||||||
argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> {
|
argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> {
|
||||||
|
@ -51,10 +51,10 @@ class UserServiceTest {
|
||||||
fun `createRemoteUser リモートユーザーを作成できる`() = runTest {
|
fun `createRemoteUser リモートユーザーを作成できる`() = runTest {
|
||||||
Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
|
Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
|
||||||
|
|
||||||
val userRepository = mock<IUserRepository> {
|
val userRepository = mock<UserRepository> {
|
||||||
onBlocking { nextId() } doReturn 113345L
|
onBlocking { nextId() } doReturn 113345L
|
||||||
}
|
}
|
||||||
val userService = UserService(userRepository, mock(), mock(), mock(), mock())
|
val userService = UserServiceImpl(userRepository, mock(), mock(), mock(), mock())
|
||||||
val user = RemoteUserCreateDto(
|
val user = RemoteUserCreateDto(
|
||||||
"test",
|
"test",
|
||||||
"example.com",
|
"example.com",
|
||||||
|
|
Loading…
Reference in New Issue