Merge branch 'develop' into feature/deliver-reaction

# Conflicts:
#	package-lock.json
#	package.json
#	src/main/kotlin/dev/usbharu/hideout/Application.kt
#	src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt
#	src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
This commit is contained in:
2023-08-08 15:28:38 +09:00
33 changed files with 921 additions and 252 deletions
@@ -15,6 +15,7 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
import dev.usbharu.hideout.exception.InvalidRefreshTokenException
import dev.usbharu.hideout.repository.IUserRepository
import dev.usbharu.hideout.routing.api.internal.v1.auth
import dev.usbharu.hideout.service.auth.IJwtService
import dev.usbharu.hideout.service.core.IMetaService
import dev.usbharu.hideout.service.user.IUserAuthService
@@ -24,6 +25,7 @@ import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.config.*
import io.ktor.server.routing.*
import io.ktor.server.testing.*
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers.anyString
@@ -70,7 +72,10 @@ class SecurityKtTest {
val jwkProvider = mock<JwkProvider>()
application {
configureSerialization()
configureSecurity(userAuthService, metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(userAuthService, userRepository, jwtService)
}
}
client.post("/login") {
@@ -97,7 +102,10 @@ class SecurityKtTest {
val jwkProvider = mock<JwkProvider>()
application {
configureSerialization()
configureSecurity(userAuthService, metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(userAuthService, userRepository, jwtService)
}
}
client.post("/login") {
contentType(ContentType.Application.Json)
@@ -122,7 +130,10 @@ class SecurityKtTest {
val jwkProvider = mock<JwkProvider>()
application {
configureSerialization()
configureSecurity(userAuthService, metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(userAuthService, userRepository, jwtService)
}
}
client.post("/login") {
contentType(ContentType.Application.Json)
@@ -140,7 +151,10 @@ class SecurityKtTest {
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check").apply {
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
@@ -155,7 +169,10 @@ class SecurityKtTest {
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "Digest dsfjjhogalkjdfmlhaog")
@@ -172,7 +189,10 @@ class SecurityKtTest {
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "")
@@ -190,7 +210,10 @@ class SecurityKtTest {
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "Bearer ")
@@ -244,11 +267,12 @@ class SecurityKtTest {
)
)
}
val userRepository = mock<IUserRepository>()
val jwtService = mock<IJwtService>()
application {
configureSerialization()
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
@@ -304,11 +328,12 @@ class SecurityKtTest {
)
)
}
val userRepository = mock<IUserRepository>()
val jwtService = mock<IJwtService>()
application {
configureSerialization()
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "Bearer $token")
@@ -362,11 +387,12 @@ class SecurityKtTest {
)
)
}
val userRepository = mock<IUserRepository>()
val jwtService = mock<IJwtService>()
application {
configureSerialization()
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "Bearer $token")
@@ -420,11 +446,12 @@ class SecurityKtTest {
)
)
}
val userRepository = mock<IUserRepository>()
val jwtService = mock<IJwtService>()
application {
configureSerialization()
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "Bearer $token")
@@ -477,11 +504,12 @@ class SecurityKtTest {
)
)
}
val userRepository = mock<IUserRepository>()
val jwtService = mock<IJwtService>()
application {
configureSerialization()
configureSecurity(mock(), metaService, userRepository, jwtService, jwkProvider)
configureSecurity(jwkProvider, metaService)
routing {
auth(mock(), mock(), mock())
}
}
client.get("/auth-check") {
header("Authorization", "Bearer $token")
@@ -501,7 +529,10 @@ class SecurityKtTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), jwtService, mock())
configureSecurity(mock(), mock())
routing {
auth(mock(), mock(), jwtService)
}
}
client.post("/refresh-token") {
header("Content-Type", "application/json")
@@ -523,7 +554,10 @@ class SecurityKtTest {
application {
configureStatusPages()
configureSerialization()
configureSecurity(mock(), mock(), mock(), jwtService, mock())
configureSecurity(mock(), mock())
routing {
auth(mock(), mock(), jwtService)
}
}
client.post("/refresh-token") {
header("Content-Type", "application/json")
@@ -4,6 +4,8 @@ import com.auth0.jwt.interfaces.Claim
import com.auth0.jwt.interfaces.Payload
import com.fasterxml.jackson.module.kotlin.readValue
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.hideout.dto.PostResponse
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
import dev.usbharu.hideout.plugins.TOKEN_AUTH
@@ -32,18 +34,27 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val posts = listOf(
Post(
PostResponse(
id = 12345,
userId = 4321,
user = user,
text = "test1",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1"
),
Post(
PostResponse(
id = 123456,
userId = 4322,
user = user,
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -64,7 +75,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -89,27 +100,35 @@ class PostsTest {
val payload = mock<Payload> {
on { getClaim(eq("uid")) } doReturn claim
}
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val posts = listOf(
Post(
PostResponse(
id = 12345,
userId = 4321,
user = user,
text = "test1",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1"
),
Post(
PostResponse(
id = 123456,
userId = 4322,
user = user,
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/2"
),
Post(
PostResponse(
id = 1234567,
userId = 4333,
user = user,
text = "Followers only",
visibility = Visibility.FOLLOWERS,
createdAt = Instant.now().toEpochMilli(),
@@ -156,9 +175,18 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val post = Post(
12345,
1234,
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val post = PostResponse(
id = 12345,
user = user,
text = "aaa",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -169,7 +197,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -187,9 +215,17 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val post = Post(
val post = PostResponse(
12345,
1234,
UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
),
text = "aaa",
visibility = Visibility.FOLLOWERS,
createdAt = Instant.now().toEpochMilli(),
@@ -242,14 +278,22 @@ class PostsTest {
onBlocking { createPost(any(), any()) } doAnswer {
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
val userId = it.getArgument<Long>(1)
Post(
123L,
userId,
null,
argument.text,
Instant.now().toEpochMilli(),
Visibility.PUBLIC,
"https://example.com"
PostResponse(
id = 123L,
user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
),
overview = null,
text = argument.text,
createdAt = Instant.now().toEpochMilli(),
visibility = Visibility.PUBLIC,
url = "https://example.com"
)
}
}
@@ -290,18 +334,27 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val posts = listOf(
Post(
PostResponse(
id = 12345,
userId = 1,
user = user,
text = "test1",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1"
),
Post(
PostResponse(
id = 123456,
userId = 1,
user = user,
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -323,7 +376,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -342,18 +395,27 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val posts = listOf(
Post(
PostResponse(
id = 12345,
userId = 1,
user = user,
text = "test1",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1"
),
Post(
PostResponse(
id = 123456,
userId = 1,
user = user,
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -375,7 +437,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -394,18 +456,27 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val posts = listOf(
Post(
PostResponse(
id = 12345,
userId = 1,
user = user,
text = "test1",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1"
),
Post(
PostResponse(
id = 123456,
userId = 1,
user = user,
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -427,7 +498,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -446,18 +517,27 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
)
val posts = listOf(
Post(
PostResponse(
id = 12345,
userId = 1,
user = user,
text = "test1",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1"
),
Post(
PostResponse(
id = 123456,
userId = 1,
user = user,
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -479,7 +559,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -498,9 +578,17 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val post = Post(
val post = PostResponse(
id = 123456,
userId = 1,
user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
),
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -511,7 +599,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -530,9 +618,17 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val post = Post(
val post = PostResponse(
id = 123456,
userId = 1,
user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
),
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -543,7 +639,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -562,9 +658,17 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val post = Post(
val post = PostResponse(
id = 123456,
userId = 1,
user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
),
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -575,7 +679,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -594,9 +698,17 @@ class PostsTest {
environment {
config = ApplicationConfig("empty.conf")
}
val post = Post(
val post = PostResponse(
id = 123456,
userId = 1,
user = UserResponse(
id = 54321,
name = "user1",
domain = "example.com",
screenName = "user 1",
description = "Test user",
url = "https://example.com/users/54321",
createdAt = Instant.now().toEpochMilli()
),
text = "test2",
visibility = Visibility.PUBLIC,
createdAt = Instant.now().toEpochMilli(),
@@ -607,7 +719,7 @@ class PostsTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
posts(postService, mock())
@@ -58,7 +58,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userService)
@@ -96,7 +96,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(userService, mock())
@@ -127,7 +127,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(userService, mock())
@@ -162,7 +162,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -195,7 +195,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -228,7 +228,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -261,7 +261,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -306,7 +306,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -351,7 +351,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -396,7 +396,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -591,7 +591,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -636,7 +636,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -681,7 +681,7 @@ class UsersTest {
}
application {
configureSerialization()
configureSecurity(mock(), mock(), mock(), mock(), mock())
configureSecurity(mock(), mock())
routing {
route("/api/internal/v1") {
users(mock(), userApiService)
@@ -48,13 +48,21 @@ class ActivityPubReceiveFollowServiceImplTest {
firstValue.invoke(scheduleContext, ReceiveFollowJob)
val actor = scheduleContext.props.props[ReceiveFollowJob.actor.name]
val targetActor = scheduleContext.props.props[ReceiveFollowJob.targetActor.name]
val follow = scheduleContext.props.props[ReceiveFollowJob.follow.name]
val follow = scheduleContext.props.props[ReceiveFollowJob.follow.name] as String
assertEquals("https://follower.example.com", actor)
assertEquals("https://example.com", targetActor)
//language=JSON
assertEquals(
"""{"type":"Follow","name":"Follow","actor":"https://follower.example.com","object":"https://example.com","@context":null}""",
follow
Json.parseToJsonElement(
"""{
"type": "Follow",
"name": "Follow",
"actor": "https://follower.example.com",
"object": "https://example.com",
"@context": null
}"""
),
Json.parseToJsonElement(follow)
)
}
}
@@ -155,7 +163,14 @@ class ActivityPubReceiveFollowServiceImplTest {
data = mapOf<String, Any>(
ReceiveFollowJob.actor.name to "https://follower.example.com",
ReceiveFollowJob.targetActor.name to "https://example.com",
ReceiveFollowJob.follow.name to """{"type":"Follow","name":"Follow","object":"https://example.com","actor":"https://follower.example.com","@context":null}"""
//language=JSON
ReceiveFollowJob.follow.name to """{
"type": "Follow",
"name": "Follow",
"object": "https://example.com",
"actor": "https://follower.example.com",
"@context": null
}"""
),
json = Json
)