diff --git a/gradle.properties b/gradle.properties index 56d141a1..9ee92fa5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,6 +6,6 @@ exposed_version=0.41.1 h2_version=2.1.214 koin_version=3.3.1 org.gradle.parallel=true -#org.gradle.configureondemand=true +org.gradle.configureondemand=true org.gradle.caching=true org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbf..ccebba77 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 50832291..42defcc9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68d..79a61d42 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt index c187a0c7..5e9da1df 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt @@ -1,7 +1,12 @@ package dev.usbharu.hideout.domain.model.ap +import com.fasterxml.jackson.databind.annotation.JsonDeserialize + open class Create : Object { + @JsonDeserialize(using = ObjectDeserializer::class) var `object`: Object? = null + var to: List = emptyList() + var cc: List = emptyList() protected constructor() : super() constructor( @@ -9,14 +14,18 @@ open class Create : Object { name: String? = null, `object`: Object?, actor: String? = null, - id: String? = null + id: String? = null, + to: List = emptyList(), + cc: List = emptyList() ) : super( - add(type, "Create"), - name, - actor, - id + type = add(type, "Create"), + name = name, + actor = actor, + id = id ) { this.`object` = `object` + this.to = to + this.cc = cc } override fun equals(other: Any?): Boolean { diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt index 97277e53..8425fc79 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt @@ -5,6 +5,9 @@ open class Note : Object { var content: String? = null var published: String? = null var to: List = emptyList() + var cc: List = emptyList() + var sensitive: Boolean = false + var inReplyTo: String? = null protected constructor() : super() constructor( @@ -14,7 +17,10 @@ open class Note : Object { attributedTo: String?, content: String?, published: String?, - to: List = emptyList() + to: List = emptyList(), + cc: List = emptyList(), + sensitive: Boolean = false, + inReplyTo: String? = null ) : super( type = add(type, "Note"), name = name, @@ -24,6 +30,9 @@ open class Note : Object { this.content = content this.published = published this.to = to + this.cc = cc + this.sensitive = sensitive + this.inReplyTo = inReplyTo } override fun equals(other: Any?): Boolean { diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt index 70bcee3b..501682ce 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.JsonNode -import dev.usbharu.hideout.service.activitypub.ActivityType +import dev.usbharu.hideout.service.activitypub.ActivityVocabulary class ObjectDeserializer : JsonDeserializer() { override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Object { @@ -22,21 +22,25 @@ class ObjectDeserializer : JsonDeserializer() { val type = treeNode["type"] val activityType = if (type.isArray) { type.firstNotNullOf { jsonNode: JsonNode -> - ActivityType.values().firstOrNull { it.name.equals(jsonNode.asText(), true) } + ActivityVocabulary.values().firstOrNull { it.name.equals(jsonNode.asText(), true) } } } else if (type.isValueNode) { - ActivityType.values().first { it.name.equals(type.asText(), true) } + ActivityVocabulary.values().first { it.name.equals(type.asText(), true) } } else { TODO() } return when (activityType) { - ActivityType.Follow -> { + ActivityVocabulary.Follow -> { val readValue = p.codec.treeToValue(treeNode, Follow::class.java) println(readValue) readValue } + ActivityVocabulary.Note -> { + p.codec.treeToValue(treeNode, Note::class.java) + } + else -> { TODO() } diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt index 661343a2..a6a5f8b8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt @@ -5,7 +5,7 @@ open class Person : Object { var summary: String? = null var inbox: String? = null var outbox: String? = null - private var url: String? = null + var url: String? = null private var icon: Image? = null var publicKey: Key? = null diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Post.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Post.kt index 2cfb45be..d58870d6 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Post.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Post.kt @@ -9,5 +9,7 @@ data class Post( val visibility: Visibility, val url: String, val repostId: Long? = null, - val replyId: Long? = null + val replyId: Long? = null, + val sensitive: Boolean = false, + val apId: String = url ) diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt index 1c6dd4a6..45af9cc2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt @@ -17,6 +17,8 @@ data class User( val createdAt: Instant ) { override fun toString(): String { - return "User(id=$id, name='$name', domain='$domain', screenName='$screenName', description='$description', password=****, inbox='$inbox', outbox='$outbox', url='$url', publicKey='$publicKey', privateKey=****, createdAt=$createdAt)" + return "User(id=$id, name='$name', domain='$domain', screenName='$screenName', description='$description'," + + " password=****, inbox='$inbox', outbox='$outbox', url='$url', publicKey='$publicKey'," + + " privateKey=****, createdAt=$createdAt)" } } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt index 38223a97..3b77248e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt @@ -5,6 +5,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.Post interface IPostRepository { suspend fun generateId(): Long suspend fun save(post: Post): Post - suspend fun findOneById(id: Long): Post + suspend fun findOneById(id: Long): Post? + suspend fun findByUrl(url: String): Post? suspend fun delete(id: Long) } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index 45101190..2d7d59a1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -16,6 +16,7 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe init { transaction(database) { SchemaUtils.create(Posts) + SchemaUtils.createMissingTablesAndColumns(Posts) } } @@ -37,14 +38,22 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe it[url] = post.url it[repostId] = post.repostId it[replyId] = post.replyId + it[sensitive] = post.sensitive + it[apId] = post.apId } return@query post } } - override suspend fun findOneById(id: Long): Post { + override suspend fun findOneById(id: Long): Post? { return query { - Posts.select { Posts.id eq id }.single().toPost() + Posts.select { Posts.id eq id }.singleOrNull()?.toPost() + } + } + + override suspend fun findByUrl(url: String): Post? { + return query { + Posts.select { Posts.url eq url }.singleOrNull()?.toPost() } } @@ -65,6 +74,8 @@ object Posts : Table() { val url = varchar("url", 500) val repostId = long("repostId").references(id).nullable() val replyId = long("replyId").references(id).nullable() + val sensitive = bool("sensitive").default(false) + val apId = varchar("ap_id", 100).uniqueIndex() override val primaryKey: PrimaryKey = PrimaryKey(id) } @@ -78,6 +89,8 @@ fun ResultRow.toPost(): Post { visibility = Visibility.values().first { visibility -> visibility.ordinal == this[Posts.visibility] }, url = this[Posts.url], repostId = this[Posts.repostId], - replyId = this[Posts.replyId] + replyId = this[Posts.replyId], + sensitive = this[Posts.sensitive], + apId = this[Posts.apId] ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateService.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateService.kt new file mode 100644 index 00000000..632c801e --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateService.kt @@ -0,0 +1,8 @@ +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 +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateServiceImpl.kt new file mode 100644 index 00000000..b73e3747 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateServiceImpl.kt @@ -0,0 +1,25 @@ +package dev.usbharu.hideout.service.activitypub + +import dev.usbharu.hideout.domain.model.ActivityPubResponse +import dev.usbharu.hideout.domain.model.ActivityPubStringResponse +import dev.usbharu.hideout.domain.model.ap.Create +import dev.usbharu.hideout.domain.model.ap.Note +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import io.ktor.http.* +import org.koin.core.annotation.Single + +@Single +class ActivityPubCreateServiceImpl( + private val activityPubNoteService: ActivityPubNoteService +) : ActivityPubCreateService { + override suspend fun receiveCreate(create: Create): ActivityPubResponse { + val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null") + if (value.type.contains("Note").not()) { + throw IllegalActivityPubObjectException("object is not Note") + } + + val note = value as Note + activityPubNoteService.fetchNote(note) + return ActivityPubStringResponse(HttpStatusCode.OK, "Created") + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt index 5c6ccf96..2c289415 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt @@ -1,5 +1,6 @@ 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 @@ -8,4 +9,7 @@ interface ActivityPubNoteService { suspend fun createNote(post: Post) suspend fun createNoteJob(props: JobProps) + + suspend fun fetchNote(url: String, targetActor: String? = null): Note + suspend fun fetchNote(note: Note, targetActor: String? = null): Note } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt index 42f0df20..15259d37 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt @@ -5,11 +5,16 @@ import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.ap.Create import dev.usbharu.hideout.domain.model.ap.Note import dev.usbharu.hideout.domain.model.hideout.entity.Post +import dev.usbharu.hideout.domain.model.hideout.entity.Visibility import dev.usbharu.hideout.domain.model.job.DeliverPostJob +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import dev.usbharu.hideout.plugins.getAp import dev.usbharu.hideout.plugins.postAp +import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.service.impl.IUserService import dev.usbharu.hideout.service.job.JobQueueParentService import io.ktor.client.* +import io.ktor.client.call.* import kjob.core.job.JobProps import org.koin.core.annotation.Single import org.slf4j.LoggerFactory @@ -19,7 +24,9 @@ import java.time.Instant class ActivityPubNoteServiceImpl( private val httpClient: HttpClient, private val jobQueueParentService: JobQueueParentService, - private val userService: IUserService + private val userService: IUserService, + private val postRepository: IPostRepository, + private val activityPubUserService: ActivityPubUserService ) : ActivityPubNoteService { private val logger = LoggerFactory.getLogger(this::class.java) @@ -46,7 +53,7 @@ class ActivityPubNoteServiceImpl( attributedTo = actor, content = postEntity.text, published = Instant.ofEpochMilli(postEntity.createdAt).toString(), - to = listOf("https://www.w3.org/ns/activitystreams#Public", actor + "/follower") + to = listOf(public, actor + "/follower") ) val inbox = props[DeliverPostJob.inbox] logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox) @@ -61,4 +68,82 @@ class ActivityPubNoteServiceImpl( ) ) } + + override suspend fun fetchNote(url: String, targetActor: String?): Note { + val post = postRepository.findByUrl(url) + if (post != null) { + val user = userService.findById(post.userId) + val reply = post.replyId?.let { postRepository.findOneById(it) } + return Note( + name = "Post", + id = post.apId, + attributedTo = user.url, + content = post.text, + published = Instant.ofEpochMilli(post.createdAt).toString(), + to = listOf(public, user.url + "/follower"), + sensitive = post.sensitive, + cc = listOf(public, user.url + "/follower"), + inReplyTo = reply?.url + ) + } + val response = httpClient.getAp( + url, + "$targetActor#pubkey" + ) + val note = response.body() + return note(note, targetActor, url) + } + + private suspend fun ActivityPubNoteServiceImpl.note( + note: Note, + targetActor: String?, + url: String + ): Note { + val person = activityPubUserService.fetchPerson( + note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), + targetActor + ) + val user = + userService.findByUrl(person.url ?: throw IllegalActivityPubObjectException("person.url is null")) + + val visibility = + if (note.to.contains(public) && note.cc.contains(public)) { + Visibility.PUBLIC + } else if (note.to.find { it.endsWith("/followers") } != null && note.cc.contains(public)) { + Visibility.UNLISTED + } else if (note.to.find { it.endsWith("/followers") } != null) { + Visibility.FOLLOWERS + } else { + Visibility.DIRECT + } + + val reply = note.inReplyTo?.let { + fetchNote(it, targetActor) + postRepository.findByUrl(it) + } + + postRepository.save( + Post( + id = postRepository.generateId(), + userId = user.id, + overview = null, + text = note.content.orEmpty(), + createdAt = Instant.parse(note.published).toEpochMilli(), + visibility = visibility, + url = note.id ?: url, + repostId = null, + replyId = reply?.id, + sensitive = note.sensitive, + apId = note.id ?: url, + ) + ) + return note + } + + override suspend fun fetchNote(note: Note, targetActor: String?): Note = + note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) + + companion object { + val public: String = "https://www.w3.org/ns/activitystreams#Public" + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt index df6f24ac..f61e825d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt @@ -43,3 +43,60 @@ enum class ActivityType { 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, +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt index 4760f05b..058fbede 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt @@ -20,7 +20,8 @@ class ActivityPubServiceImpl( private val activityPubReceiveFollowService: ActivityPubReceiveFollowService, private val activityPubNoteService: ActivityPubNoteService, private val activityPubUndoService: ActivityPubUndoService, - private val activityPubAcceptService: ActivityPubAcceptService + private val activityPubAcceptService: ActivityPubAcceptService, + private val activityPubCreateService: ActivityPubCreateService ) : ActivityPubService { val logger: Logger = LoggerFactory.getLogger(this::class.java) @@ -32,9 +33,9 @@ class ActivityPubServiceImpl( } val type = readTree["type"] if (type.isArray) { - return type.mapNotNull { jsonNode: JsonNode -> + return type.firstNotNullOf { jsonNode: JsonNode -> ActivityType.values().firstOrNull { it.name.equals(jsonNode.asText(), true) } - }.first() + } } return ActivityType.values().first { it.name.equals(type.asText(), true) } } @@ -51,6 +52,7 @@ class ActivityPubServiceImpl( ) ) + ActivityType.Create -> activityPubCreateService.receiveCreate(configData.objectMapper.readValue(json)) ActivityType.Undo -> activityPubUndoService.receiveUndo(configData.objectMapper.readValue(json)) else -> { @@ -62,7 +64,10 @@ class ActivityPubServiceImpl( override suspend fun processActivity(job: JobContextWithProps, hideoutJob: HideoutJob) { logger.debug("processActivity: ${hideoutJob.name}") when (hideoutJob) { - ReceiveFollowJob -> activityPubReceiveFollowService.receiveFollowJob(job.props as JobProps) + ReceiveFollowJob -> activityPubReceiveFollowService.receiveFollowJob( + job.props as JobProps + ) + DeliverPostJob -> activityPubNoteService.createNoteJob(job.props as JobProps) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt index d8bf3e5d..ab6c32fd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt @@ -9,6 +9,7 @@ import io.ktor.http.* import org.koin.core.annotation.Single @Single +@Suppress("UnsafeCallOnNullableType") class ActivityPubUndoServiceImpl( private val userService: IUserService, private val activityPubUserService: ActivityPubUserService diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 4593b633..ad457f2b 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -4,7 +4,7 @@ %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - + diff --git a/src/test/kotlin/dev/usbharu/hideout/domain/model/ap/UndoTest.kt b/src/test/kotlin/dev/usbharu/hideout/domain/model/ap/UndoTest.kt index 0e34e75e..cc02183e 100644 --- a/src/test/kotlin/dev/usbharu/hideout/domain/model/ap/UndoTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/domain/model/ap/UndoTest.kt @@ -30,7 +30,8 @@ class UndoTest { @Test fun Undoをデシリアライズ出来る() { - @Language("JSON") val json = """ + @Language("JSON") + val json = """ { "@context": [ "https://www.w3.org/ns/activitystreams", diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt index e788e4bb..c00503c6 100644 --- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt @@ -92,6 +92,18 @@ class ActivityPubKtTest { TODO("Not yet implemented") } + override suspend fun addFollowRequest(id: Long, follower: Long) { + TODO("Not yet implemented") + } + + override suspend fun deleteFollowRequest(id: Long, follower: Long) { + TODO("Not yet implemented") + } + + override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean { + TODO("Not yet implemented") + } + override suspend fun nextId(): Long { TODO("Not yet implemented") } diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt index 710b2620..1a737b4b 100644 --- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt @@ -88,6 +88,18 @@ class KtorKeyMapTest { TODO("Not yet implemented") } + override suspend fun addFollowRequest(id: Long, follower: Long) { + TODO("Not yet implemented") + } + + override suspend fun deleteFollowRequest(id: Long, follower: Long) { + TODO("Not yet implemented") + } + + override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean { + TODO("Not yet implemented") + } + override suspend fun nextId(): Long { TODO("Not yet implemented") } diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImplTest.kt index 396ecc08..ce44343f 100644 --- a/src/test/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImplTest.kt @@ -41,11 +41,14 @@ class JwtRefreshTokenRepositoryImplTest { @Test fun `save 存在しない場合はinsertする`() = runTest { - val repository = JwtRefreshTokenRepositoryImpl(db, object : IdGenerateService { - override suspend fun generateId(): Long { - TODO("Not yet implemented") + val repository = JwtRefreshTokenRepositoryImpl( + db, + object : IdGenerateService { + override suspend fun generateId(): Long { + TODO("Not yet implemented") + } } - }) + ) val now = Instant.now(Clock.tickMillis(ZoneId.systemDefault())) val expiresAt = now.plus(10, ChronoUnit.MINUTES) @@ -57,11 +60,14 @@ class JwtRefreshTokenRepositoryImplTest { @Test fun `save 存在する場合はupdateする`() = runTest { - val repository = JwtRefreshTokenRepositoryImpl(db, object : IdGenerateService { - override suspend fun generateId(): Long { - TODO("Not yet implemented") + val repository = JwtRefreshTokenRepositoryImpl( + db, + object : IdGenerateService { + override suspend fun generateId(): Long { + TODO("Not yet implemented") + } } - }) + ) transaction { JwtRefreshTokens.insert { it[id] = 1L diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt index aab82880..8fb127f7 100644 --- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt @@ -28,6 +28,7 @@ class UserRepositoryTest { transaction(db) { SchemaUtils.create(Users) SchemaUtils.create(UsersFollowers) + SchemaUtils.create(FollowRequests) } } @@ -35,6 +36,7 @@ class UserRepositoryTest { fun tearDown() { transaction(db) { SchemaUtils.drop(UsersFollowers) + SchemaUtils.drop(FollowRequests) SchemaUtils.drop(Users) } } @@ -96,9 +98,7 @@ class UserRepositoryTest { ) userRepository.createFollower(user.id, follower.id) userRepository.createFollower(user.id, follower2.id) - userRepository.findFollowersById(user.id).let { - assertIterableEquals(listOf(follower, follower2), it) - } + assertIterableEquals(listOf(follower, follower2), userRepository.findFollowersById(user.id)) } @Test diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/ContentTypeRouteSelectorTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/ContentTypeRouteSelectorTest.kt index 71513fef..b10e2a07 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/ContentTypeRouteSelectorTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/ContentTypeRouteSelectorTest.kt @@ -30,7 +30,7 @@ class ContentTypeRouteSelectorTest { } } - client.get("/test"){ + client.get("/test") { accept(ContentType.Text.Html) }.apply { assertEquals("NG", bodyAsText()) @@ -60,7 +60,7 @@ class ContentTypeRouteSelectorTest { } } - client.get("/test"){ + client.get("/test") { accept(ContentType.Text.Html) }.apply { assertEquals("NG", bodyAsText()) @@ -85,7 +85,7 @@ class ContentTypeRouteSelectorTest { } } - client.get("/test"){ + client.get("/test") { accept(ContentType.Text.Html) }.apply { assertEquals("NG", bodyAsText()) @@ -114,18 +114,18 @@ class ContentTypeRouteSelectorTest { } } - client.get("/test"){ + client.get("/test") { accept(ContentType.Text.Html) }.apply { assertEquals("OK", bodyAsText()) } - client.get("/test"){ + client.get("/test") { accept(ContentType.Application.Json) }.apply { assertEquals("OK", bodyAsText()) } - client.get("/test"){ + client.get("/test") { accept(ContentType.Application.Xml) }.apply { assertEquals("NG", bodyAsText()) diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt index 901acc89..5b878534 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt @@ -158,8 +158,12 @@ class PostsTest { config = ApplicationConfig("empty.conf") } val post = Post( - 12345, 1234, text = "aaa", visibility = Visibility.PUBLIC, - createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/1" + 12345, + 1234, + text = "aaa", + visibility = Visibility.PUBLIC, + createdAt = Instant.now().toEpochMilli(), + url = "https://example.com/posts/1" ) val postService = mock { onBlocking { findByIdForUser(any(), anyOrNull()) } doReturn post @@ -185,8 +189,12 @@ class PostsTest { config = ApplicationConfig("empty.conf") } val post = Post( - 12345, 1234, text = "aaa", visibility = Visibility.FOLLOWERS, - createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/1" + 12345, + 1234, + text = "aaa", + visibility = Visibility.FOLLOWERS, + createdAt = Instant.now().toEpochMilli(), + url = "https://example.com/posts/1" ) val postService = mock { onBlocking { findByIdForUser(any(), isNotNull()) } doReturn post @@ -247,7 +255,6 @@ class PostsTest { } application { authentication { - bearer(TOKEN_AUTH) { authenticate { println("aaaaaaaaaaaa") diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt index 91da7b03..dffe7ab8 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt @@ -290,7 +290,8 @@ class UsersTest { "test User", "https://example.com/test", Instant.now().toEpochMilli() - ), UserResponse( + ), + UserResponse( 1236, "follower2", "example.com", @@ -334,7 +335,8 @@ class UsersTest { "test User", "https://example.com/test", Instant.now().toEpochMilli() - ), UserResponse( + ), + UserResponse( 1236, "follower2", "example.com", @@ -378,7 +380,8 @@ class UsersTest { "test User", "https://example.com/test", Instant.now().toEpochMilli() - ), UserResponse( + ), + UserResponse( 1236, "follower2", "example.com", @@ -572,7 +575,8 @@ class UsersTest { "test User", "https://example.com/test", Instant.now().toEpochMilli() - ), UserResponse( + ), + UserResponse( 1236, "follower2", "example.com", @@ -616,7 +620,8 @@ class UsersTest { "test User", "https://example.com/test", Instant.now().toEpochMilli() - ), UserResponse( + ), + UserResponse( 1236, "follower2", "example.com", @@ -660,7 +665,8 @@ class UsersTest { "test User", "https://example.com/test", Instant.now().toEpochMilli() - ), UserResponse( + ), + UserResponse( 1236, "follower2", "example.com", diff --git a/src/test/kotlin/dev/usbharu/hideout/service/MetaServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/MetaServiceImplTest.kt index 46ab3715..f484d51f 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/MetaServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/MetaServiceImplTest.kt @@ -37,7 +37,6 @@ class MetaServiceImplTest { @Test fun `updateMeta メタデータを保存できる`() = runTest { - val meta = Meta("1.0.1", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) val metaRepository = mock { onBlocking { save(any()) } doReturn Unit diff --git a/src/test/kotlin/dev/usbharu/hideout/service/ServerInitialiseServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/ServerInitialiseServiceImplTest.kt index 791e349a..3b6e34c0 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/ServerInitialiseServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/ServerInitialiseServiceImplTest.kt @@ -23,23 +23,23 @@ class ServerInitialiseServiceImplTest { val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository) serverInitialiseServiceImpl.init() - verify(metaRepository,times(1)).save(any()) + verify(metaRepository, times(1)).save(any()) } @Test 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 { onBlocking { get() } doReturn meta } val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository) serverInitialiseServiceImpl.init() - verify(metaRepository,times(0)).save(any()) + verify(metaRepository, times(0)).save(any()) } @Test 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 { onBlocking { get() } doReturn meta onBlocking { save(any()) } doReturn Unit @@ -47,10 +47,10 @@ class ServerInitialiseServiceImplTest { val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository) serverInitialiseServiceImpl.init() - verify(metaRepository,times(1)).save(any()) + verify(metaRepository, times(1)).save(any()) argumentCaptor { - verify(metaRepository,times(1)).save(capture()) - assertEquals(ServerUtil.getImplementationVersion(),firstValue.version) + verify(metaRepository, times(1)).save(capture()) + assertEquals(ServerUtil.getImplementationVersion(), firstValue.version) } } } diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt index 0372f88e..f4a9f206 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt @@ -72,7 +72,8 @@ class ActivityPubNoteServiceImplTest { onBlocking { findFollowersById(eq(1L)) } doReturn followers } val jobQueueParentService = mock() - val activityPubNoteService = ActivityPubNoteServiceImpl(mock(), jobQueueParentService, userService) + val activityPubNoteService = + ActivityPubNoteServiceImpl(mock(), jobQueueParentService, userService, mock(), mock()) val postEntity = Post( 1L, 1L, @@ -95,7 +96,7 @@ class ActivityPubNoteServiceImplTest { respondOk() } ) - val activityPubNoteService = ActivityPubNoteServiceImpl(httpClient, mock(), mock()) + val activityPubNoteService = ActivityPubNoteServiceImpl(httpClient, mock(), mock(), mock(), mock()) activityPubNoteService.createNoteJob( JobProps( data = mapOf( diff --git a/src/test/kotlin/dev/usbharu/hideout/service/impl/PostServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/impl/PostServiceTest.kt index 46e41fd2..47ea8518 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/impl/PostServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/impl/PostServiceTest.kt @@ -53,7 +53,7 @@ class PostServiceTest { text, Instant.now().toEpochMilli(), visibility, - "https://example.com" + "https://example.com${(userId.toString() + text).hashCode()}" ) } @@ -88,6 +88,8 @@ class PostServiceTest { this[Posts.url] = it.url this[Posts.replyId] = it.replyId this[Posts.repostId] = it.repostId + this[Posts.sensitive] = it.sensitive + this[Posts.apId] = it.apId } } @@ -109,7 +111,7 @@ class PostServiceTest { text, Instant.now().toEpochMilli(), visibility, - "https://example.com" + "https://example.com${(userId.toString() + text).hashCode()}" ) } @@ -148,6 +150,8 @@ class PostServiceTest { this[Posts.url] = it.url this[Posts.replyId] = it.replyId this[Posts.repostId] = it.repostId + this[Posts.sensitive] = it.sensitive + this[Posts.apId] = it.apId } UsersFollowers.insert { it[id] = 100L