mirror of https://github.com/usbharu/Hideout.git
refactor: Ktorに関連するテストを削除
This commit is contained in:
parent
9b68f1941f
commit
b8e4d2dc3b
|
@ -1,573 +0,0 @@
|
||||||
package dev.usbharu.hideout.plugins
|
|
||||||
|
|
||||||
import com.auth0.jwk.Jwk
|
|
||||||
import com.auth0.jwk.JwkProvider
|
|
||||||
import com.auth0.jwt.JWT
|
|
||||||
import com.auth0.jwt.algorithms.Algorithm
|
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
|
||||||
import dev.usbharu.hideout.config.Config
|
|
||||||
import dev.usbharu.hideout.config.ConfigData
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
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.exception.InvalidUsernameOrPasswordException
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.routing.api.internal.v1.auth
|
|
||||||
import dev.usbharu.hideout.service.api.UserAuthApiService
|
|
||||||
import dev.usbharu.hideout.service.auth.JwtService
|
|
||||||
import dev.usbharu.hideout.service.core.MetaService
|
|
||||||
import dev.usbharu.hideout.service.user.UserAuthService
|
|
||||||
import dev.usbharu.hideout.util.Base64Util
|
|
||||||
import dev.usbharu.hideout.util.JsonWebKeyUtil
|
|
||||||
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
|
|
||||||
import org.mockito.kotlin.*
|
|
||||||
import java.security.KeyPairGenerator
|
|
||||||
import java.security.interfaces.RSAPrivateKey
|
|
||||||
import java.security.interfaces.RSAPublicKey
|
|
||||||
import java.time.Instant
|
|
||||||
import java.time.temporal.ChronoUnit
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class SecurityKtTest {
|
|
||||||
@Test
|
|
||||||
fun `login ログイン出来るか`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
val jwtToken = JwtToken("Token", "RefreshToken")
|
|
||||||
val userAuthService = mock<UserAuthApiService> {
|
|
||||||
onBlocking { login(eq("testUser"), eq("password")) } doReturn jwtToken
|
|
||||||
}
|
|
||||||
val metaService = mock<MetaService>()
|
|
||||||
val userQueryService = mock<UserQueryService> {
|
|
||||||
onBlocking { findByNameAndDomain(eq("testUser"), eq("example.com")) } doReturn User.of(
|
|
||||||
id = 1L,
|
|
||||||
name = "testUser",
|
|
||||||
domain = "example.com",
|
|
||||||
screenName = "test",
|
|
||||||
description = "",
|
|
||||||
password = "hashedPassword",
|
|
||||||
inbox = "https://example.com/inbox",
|
|
||||||
outbox = "https://example.com/outbox",
|
|
||||||
url = "https://example.com/profile",
|
|
||||||
publicKey = "",
|
|
||||||
privateKey = "",
|
|
||||||
createdAt = Instant.now()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val jwkProvider = mock<JwkProvider>()
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(userAuthService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.post("/login") {
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(UserLogin("testUser", "password")))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, call.response.status)
|
|
||||||
assertEquals(jwtToken, Config.configData.objectMapper.readValue(call.response.bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `login 存在しないユーザーのログインに失敗する`() {
|
|
||||||
testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
mock<UserAuthService> {
|
|
||||||
onBlocking { verifyAccount(anyString(), anyString()) }.doReturn(false)
|
|
||||||
}
|
|
||||||
val metaService = mock<MetaService>()
|
|
||||||
mock<UserQueryService>()
|
|
||||||
mock<JwtService>()
|
|
||||||
val jwkProvider = mock<JwkProvider>()
|
|
||||||
val userAuthApiService = mock<UserAuthApiService> {
|
|
||||||
onBlocking { login(anyString(), anyString()) } doThrow InvalidUsernameOrPasswordException()
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureStatusPages()
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(userAuthApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.post("/login") {
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(UserLogin("InvalidTtestUser", "password")))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `login 不正なパスワードのログインに失敗する`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
val metaService = mock<MetaService>()
|
|
||||||
val jwkProvider = mock<JwkProvider>()
|
|
||||||
val userAuthApiService = mock<UserAuthApiService> {
|
|
||||||
onBlocking { login(anyString(), eq("InvalidPassword")) } doThrow InvalidUsernameOrPasswordException()
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureStatusPages()
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(userAuthApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.post("/login") {
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(UserLogin("TestUser", "InvalidPassword")))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check Authorizedヘッダーが無いと401が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check").apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check Authorizedヘッダーの形式が間違っていると401が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Digest dsfjjhogalkjdfmlhaog")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check Authorizedヘッダーが空だと401が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check AuthorizedヘッダーがBeararで空だと401が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
|
|
||||||
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Bearer ")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check 正当なJWTだとアクセスできる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(2048)
|
|
||||||
val keyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
val rsaPublicKey = keyPair.public as RSAPublicKey
|
|
||||||
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
|
|
||||||
val now = Instant.now()
|
|
||||||
val kid = UUID.randomUUID()
|
|
||||||
val token = JWT.create()
|
|
||||||
.withAudience("${Config.configData.url}/users/test")
|
|
||||||
.withIssuer(Config.configData.url)
|
|
||||||
.withKeyId(kid.toString())
|
|
||||||
.withClaim("uid", 123456L)
|
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
|
||||||
val metaService = mock<MetaService> {
|
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
|
||||||
Jwt(
|
|
||||||
kid,
|
|
||||||
Base64Util.encode(keyPair.private.encoded),
|
|
||||||
Base64Util.encode(rsaPublicKey.encoded)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValue = Config.configData.objectMapper.readerFor(Map::class.java)
|
|
||||||
.readValue<MutableMap<String, Any>?>(
|
|
||||||
JsonWebKeyUtil.publicKeyToJwk(
|
|
||||||
rsaPublicKey,
|
|
||||||
kid.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val jwkProvider = mock<JwkProvider> {
|
|
||||||
onBlocking { get(anyString()) }.doReturn(
|
|
||||||
Jwk.fromValues(
|
|
||||||
(readValue["keys"] as List<Map<String, Any>>)[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Bearer $token")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, call.response.status)
|
|
||||||
assertEquals("Hello 123456", call.response.bodyAsText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check 期限切れのトークンではアクセスできない`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(2048)
|
|
||||||
val keyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
val rsaPublicKey = keyPair.public as RSAPublicKey
|
|
||||||
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
|
|
||||||
val now = Instant.now()
|
|
||||||
val kid = UUID.randomUUID()
|
|
||||||
val token = JWT.create()
|
|
||||||
.withAudience("${Config.configData.url}/users/test")
|
|
||||||
.withIssuer(Config.configData.url)
|
|
||||||
.withKeyId(kid.toString())
|
|
||||||
.withClaim("uid", 123345L)
|
|
||||||
.withExpiresAt(now.minus(30, ChronoUnit.MINUTES))
|
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
|
||||||
val metaService = mock<MetaService> {
|
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
|
||||||
Jwt(
|
|
||||||
kid,
|
|
||||||
Base64Util.encode(keyPair.private.encoded),
|
|
||||||
Base64Util.encode(rsaPublicKey.encoded)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValue = Config.configData.objectMapper.readerFor(Map::class.java)
|
|
||||||
.readValue<MutableMap<String, Any>?>(
|
|
||||||
JsonWebKeyUtil.publicKeyToJwk(
|
|
||||||
rsaPublicKey,
|
|
||||||
kid.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val jwkProvider = mock<JwkProvider> {
|
|
||||||
onBlocking { get(anyString()) }.doReturn(
|
|
||||||
Jwk.fromValues(
|
|
||||||
(readValue["keys"] as List<Map<String, Any>>)[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Bearer $token")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check issuerが間違っているとアクセスできない`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(2048)
|
|
||||||
val keyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
val rsaPublicKey = keyPair.public as RSAPublicKey
|
|
||||||
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
|
|
||||||
val now = Instant.now()
|
|
||||||
val kid = UUID.randomUUID()
|
|
||||||
val token = JWT.create()
|
|
||||||
.withAudience("${Config.configData.url}/users/test")
|
|
||||||
.withIssuer("https://example.com")
|
|
||||||
.withKeyId(kid.toString())
|
|
||||||
.withClaim("uid", 12345L)
|
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
|
||||||
val metaService = mock<MetaService> {
|
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
|
||||||
Jwt(
|
|
||||||
kid,
|
|
||||||
Base64Util.encode(keyPair.private.encoded),
|
|
||||||
Base64Util.encode(rsaPublicKey.encoded)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValue = Config.configData.objectMapper.readerFor(Map::class.java)
|
|
||||||
.readValue<MutableMap<String, Any>?>(
|
|
||||||
JsonWebKeyUtil.publicKeyToJwk(
|
|
||||||
rsaPublicKey,
|
|
||||||
kid.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val jwkProvider = mock<JwkProvider> {
|
|
||||||
onBlocking { get(anyString()) }.doReturn(
|
|
||||||
Jwk.fromValues(
|
|
||||||
(readValue["keys"] as List<Map<String, Any>>)[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Bearer $token")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check usernameが空だと失敗する`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(2048)
|
|
||||||
val keyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
val rsaPublicKey = keyPair.public as RSAPublicKey
|
|
||||||
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
|
|
||||||
val now = Instant.now()
|
|
||||||
val kid = UUID.randomUUID()
|
|
||||||
val token = JWT.create()
|
|
||||||
.withAudience("${Config.configData.url}/users/test")
|
|
||||||
.withIssuer(Config.configData.url)
|
|
||||||
.withKeyId(kid.toString())
|
|
||||||
.withClaim("uid", null as Long?)
|
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
|
||||||
val metaService = mock<MetaService> {
|
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
|
||||||
Jwt(
|
|
||||||
kid,
|
|
||||||
Base64Util.encode(keyPair.private.encoded),
|
|
||||||
Base64Util.encode(rsaPublicKey.encoded)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValue = Config.configData.objectMapper.readerFor(Map::class.java)
|
|
||||||
.readValue<MutableMap<String, Any>?>(
|
|
||||||
JsonWebKeyUtil.publicKeyToJwk(
|
|
||||||
rsaPublicKey,
|
|
||||||
kid.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val jwkProvider = mock<JwkProvider> {
|
|
||||||
onBlocking { get(anyString()) }.doReturn(
|
|
||||||
Jwk.fromValues(
|
|
||||||
(readValue["keys"] as List<Map<String, Any>>)[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Bearer $token")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `auth-check usernameが存在しないと失敗する`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
|
|
||||||
keyPairGenerator.initialize(2048)
|
|
||||||
val keyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
val rsaPublicKey = keyPair.public as RSAPublicKey
|
|
||||||
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
|
|
||||||
val now = Instant.now()
|
|
||||||
val kid = UUID.randomUUID()
|
|
||||||
val token = JWT.create()
|
|
||||||
.withAudience("${Config.configData.url}/users/test")
|
|
||||||
.withIssuer(Config.configData.url)
|
|
||||||
.withKeyId(kid.toString())
|
|
||||||
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
|
|
||||||
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
|
|
||||||
val metaService = mock<MetaService> {
|
|
||||||
onBlocking { getJwtMeta() }.doReturn(
|
|
||||||
Jwt(
|
|
||||||
kid,
|
|
||||||
Base64Util.encode(keyPair.private.encoded),
|
|
||||||
Base64Util.encode(rsaPublicKey.encoded)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValue = Config.configData.objectMapper.readerFor(Map::class.java)
|
|
||||||
.readValue<MutableMap<String, Any>?>(
|
|
||||||
JsonWebKeyUtil.publicKeyToJwk(
|
|
||||||
rsaPublicKey,
|
|
||||||
kid.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val jwkProvider = mock<JwkProvider> {
|
|
||||||
onBlocking { get(anyString()) }.doReturn(
|
|
||||||
Jwk.fromValues(
|
|
||||||
(readValue["keys"] as List<Map<String, Any>>)[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(jwkProvider, metaService)
|
|
||||||
routing {
|
|
||||||
auth(mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/auth-check") {
|
|
||||||
header("Authorization", "Bearer $token")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Unauthorized, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `refresh-token リフレッシュトークンが正当だとトークンを発行する`() = testApplication {
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val jwtService = mock<UserAuthApiService> {
|
|
||||||
onBlocking { refreshToken(any()) }.doReturn(JwtToken("token", "refreshToken2"))
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
auth(jwtService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.post("/refresh-token") {
|
|
||||||
header("Content-Type", "application/json")
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(RefreshToken("refreshToken")))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `refresh-token リフレッシュトークンが不正だと失敗する`() = testApplication {
|
|
||||||
Config.configData = ConfigData(url = "https://localhost", objectMapper = jacksonObjectMapper())
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val jwtService = mock<UserAuthApiService> {
|
|
||||||
onBlocking { refreshToken(any()) } doThrow InvalidRefreshTokenException("Invalid Refresh Token")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureStatusPages()
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
auth(jwtService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.post("/refresh-token") {
|
|
||||||
header("Content-Type", "application/json")
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(RefreshToken("InvalidRefreshToken")))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.BadRequest, call.response.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,134 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing.activitypub
|
|
||||||
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.client.statement.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.server.application.*
|
|
||||||
import io.ktor.server.config.*
|
|
||||||
import io.ktor.server.response.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
import io.ktor.server.testing.*
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class ContentTypeRouteSelectorTest {
|
|
||||||
@Test
|
|
||||||
fun `Content-Typeが一つでマッチする`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
routing {
|
|
||||||
route("/test") {
|
|
||||||
createChild(ContentTypeRouteSelector(ContentType.Application.Json)).handle {
|
|
||||||
call.respondText("OK")
|
|
||||||
}
|
|
||||||
get {
|
|
||||||
call.respondText("NG")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Text.Html)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("NG", bodyAsText())
|
|
||||||
}
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Application.Json)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("OK", bodyAsText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Content-Typeが一つのとき違うとマッチしない`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
routing {
|
|
||||||
route("/test") {
|
|
||||||
createChild(ContentTypeRouteSelector(ContentType.Application.Json)).handle {
|
|
||||||
call.respondText("OK")
|
|
||||||
}
|
|
||||||
get {
|
|
||||||
call.respondText("NG")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Text.Html)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("NG", bodyAsText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Content-Typeがからのときマッチしない`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
routing {
|
|
||||||
route("/test") {
|
|
||||||
createChild(ContentTypeRouteSelector()).handle {
|
|
||||||
call.respondText("OK")
|
|
||||||
}
|
|
||||||
get {
|
|
||||||
call.respondText("NG")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Text.Html)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("NG", bodyAsText())
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/test").apply {
|
|
||||||
assertEquals("NG", bodyAsText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `Content-Typeが複数指定されていてマッチする`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
routing {
|
|
||||||
route("/test") {
|
|
||||||
createChild(ContentTypeRouteSelector(ContentType.Application.Json, ContentType.Text.Html)).handle {
|
|
||||||
call.respondText("OK")
|
|
||||||
}
|
|
||||||
get {
|
|
||||||
call.respondText("NG")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Text.Html)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("OK", bodyAsText())
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Application.Json)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("OK", bodyAsText())
|
|
||||||
}
|
|
||||||
client.get("/test") {
|
|
||||||
accept(ContentType.Application.Xml)
|
|
||||||
}.apply {
|
|
||||||
assertEquals("NG", bodyAsText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing.activitypub
|
|
||||||
|
|
||||||
import dev.usbharu.hideout.exception.JsonParseException
|
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
|
||||||
import dev.usbharu.hideout.plugins.configureStatusPages
|
|
||||||
import dev.usbharu.hideout.service.ap.APService
|
|
||||||
import dev.usbharu.hideout.service.ap.APUserService
|
|
||||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
|
||||||
import dev.usbharu.hideout.service.user.UserService
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.server.config.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
import io.ktor.server.testing.*
|
|
||||||
import org.junit.jupiter.api.Assertions
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.mockito.kotlin.any
|
|
||||||
import org.mockito.kotlin.doReturn
|
|
||||||
import org.mockito.kotlin.doThrow
|
|
||||||
import org.mockito.kotlin.mock
|
|
||||||
|
|
||||||
class InboxRoutingKtTest {
|
|
||||||
@Test
|
|
||||||
fun `sharedInboxにGETしたら405が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
inbox(mock(), mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/inbox").let {
|
|
||||||
Assertions.assertEquals(HttpStatusCode.MethodNotAllowed, it.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `sharedInboxに空のリクエストボディでPOSTしたら400が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {
|
|
||||||
on { verify(any()) } doReturn true
|
|
||||||
}
|
|
||||||
val apService = mock<APService> {
|
|
||||||
on { parseActivity(any()) } doThrow JsonParseException()
|
|
||||||
}
|
|
||||||
mock<UserService>()
|
|
||||||
mock<APUserService>()
|
|
||||||
application {
|
|
||||||
configureStatusPages()
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
inbox(httpSignatureVerifyService, apService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.post("/inbox").let {
|
|
||||||
Assertions.assertEquals(HttpStatusCode.BadRequest, it.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `ユーザのinboxにGETしたら405が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
inbox(mock(), mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/users/test/inbox").let {
|
|
||||||
Assertions.assertEquals(HttpStatusCode.MethodNotAllowed, it.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `ユーザーのinboxに空のリクエストボディでPOSTしたら400が帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {
|
|
||||||
on { verify(any()) } doReturn true
|
|
||||||
}
|
|
||||||
val apService = mock<APService> {
|
|
||||||
on { parseActivity(any()) } doThrow JsonParseException()
|
|
||||||
}
|
|
||||||
mock<UserService>()
|
|
||||||
mock<APUserService>()
|
|
||||||
application {
|
|
||||||
configureStatusPages()
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
inbox(httpSignatureVerifyService, apService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.post("/users/test/inbox").let {
|
|
||||||
Assertions.assertEquals(HttpStatusCode.BadRequest, it.status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,202 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing.activitypub
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude
|
|
||||||
import com.fasterxml.jackson.annotation.JsonSetter
|
|
||||||
import com.fasterxml.jackson.annotation.Nulls
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Image
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Key
|
|
||||||
import dev.usbharu.hideout.domain.model.ap.Person
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
|
||||||
import dev.usbharu.hideout.query.UserQueryService
|
|
||||||
import dev.usbharu.hideout.service.ap.APUserService
|
|
||||||
import dev.usbharu.hideout.util.HttpUtil.Activity
|
|
||||||
import dev.usbharu.hideout.util.HttpUtil.JsonLd
|
|
||||||
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
|
|
||||||
import org.mockito.kotlin.doReturn
|
|
||||||
import org.mockito.kotlin.eq
|
|
||||||
import org.mockito.kotlin.mock
|
|
||||||
import utils.TestTransaction
|
|
||||||
import java.time.Instant
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
class UsersAPTest {
|
|
||||||
|
|
||||||
@Test()
|
|
||||||
fun `ユーザのURLにAcceptヘッダーをActivityにしてアクセスしたときPersonが返ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val person = Person(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "test",
|
|
||||||
id = "http://example.com/users/test",
|
|
||||||
preferredUsername = "test",
|
|
||||||
summary = "test user",
|
|
||||||
inbox = "http://example.com/users/test/inbox",
|
|
||||||
outbox = "http://example.com/users/test/outbox",
|
|
||||||
url = "http://example.com/users/test",
|
|
||||||
icon = Image(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "http://example.com/users/test/icon.png",
|
|
||||||
mediaType = "image/png",
|
|
||||||
url = "http://example.com/users/test/icon.png"
|
|
||||||
),
|
|
||||||
publicKey = Key(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "Public Key",
|
|
||||||
id = "http://example.com/users/test#pubkey",
|
|
||||||
owner = "https://example.com/users/test",
|
|
||||||
publicKeyPem = "-----BEGIN PUBLIC KEY-----\n\n-----END PUBLIC KEY-----"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
person.context = listOf("https://www.w3.org/ns/activitystreams")
|
|
||||||
|
|
||||||
val apUserService = mock<APUserService> {
|
|
||||||
onBlocking { getPersonByName(anyString()) } doReturn person
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
usersAP(apUserService, mock(), mock(), TestTransaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/users/test") {
|
|
||||||
accept(ContentType.Application.Activity)
|
|
||||||
}.let {
|
|
||||||
val objectMapper = jacksonObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
|
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
|
||||||
objectMapper.configOverride(List::class.java).setSetterInfo(
|
|
||||||
JsonSetter.Value.forValueNulls(
|
|
||||||
Nulls.AS_EMPTY
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val actual = it.bodyAsText()
|
|
||||||
val readValue = objectMapper.readValue<Person>(actual)
|
|
||||||
assertEquals(person, readValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Disabled
|
|
||||||
@Test()
|
|
||||||
fun `ユーザのURLにAcceptヘッダーをActivityとJson-LDにしてアクセスしたときPersonが返ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val person = Person(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "test",
|
|
||||||
id = "http://example.com/users/test",
|
|
||||||
preferredUsername = "test",
|
|
||||||
summary = "test user",
|
|
||||||
inbox = "http://example.com/users/test/inbox",
|
|
||||||
outbox = "http://example.com/users/test/outbox",
|
|
||||||
url = "http://example.com/users/test",
|
|
||||||
icon = Image(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "http://example.com/users/test/icon.png",
|
|
||||||
mediaType = "image/png",
|
|
||||||
url = "http://example.com/users/test/icon.png"
|
|
||||||
),
|
|
||||||
publicKey = Key(
|
|
||||||
type = emptyList(),
|
|
||||||
name = "Public Key",
|
|
||||||
id = "http://example.com/users/test#pubkey",
|
|
||||||
owner = "https://example.com/users/test",
|
|
||||||
publicKeyPem = "-----BEGIN PUBLIC KEY-----\n\n-----END PUBLIC KEY-----"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
person.context = listOf("https://www.w3.org/ns/activitystreams")
|
|
||||||
|
|
||||||
val apUserService = mock<APUserService> {
|
|
||||||
onBlocking { getPersonByName(anyString()) } doReturn person
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
usersAP(apUserService, mock(), mock(), TestTransaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/users/test") {
|
|
||||||
accept(ContentType.Application.JsonLd)
|
|
||||||
accept(ContentType.Application.Activity)
|
|
||||||
}.let {
|
|
||||||
val objectMapper = jacksonObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
|
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
|
||||||
objectMapper.configOverride(List::class.java).setSetterInfo(
|
|
||||||
JsonSetter.Value.forValueNulls(
|
|
||||||
Nulls.AS_EMPTY
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val actual = it.bodyAsText()
|
|
||||||
val readValue = objectMapper.readValue<Person>(actual)
|
|
||||||
assertEquals(person, readValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Disabled
|
|
||||||
@Test
|
|
||||||
fun contentType_Test() {
|
|
||||||
assertTrue(ContentType.Application.Activity.match("application/activity+json"))
|
|
||||||
val listOf = listOf(ContentType.Application.JsonLd, ContentType.Application.Activity)
|
|
||||||
assertTrue(
|
|
||||||
listOf.find { contentType ->
|
|
||||||
contentType.match("application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")
|
|
||||||
}.let { it != null }
|
|
||||||
)
|
|
||||||
assertTrue(
|
|
||||||
ContentType.Application.JsonLd.match(
|
|
||||||
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun ユーザーのURLにAcceptヘッダーをhtmlにしてアクセスしたときはただの文字を返す() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userService = mock<UserQueryService> {
|
|
||||||
onBlocking { findByNameAndDomain(eq("test"), anyString()) } doReturn User.of(
|
|
||||||
1L,
|
|
||||||
"test",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"",
|
|
||||||
"hashedPassword",
|
|
||||||
"https://example.com/inbox",
|
|
||||||
"https://example.com/outbox",
|
|
||||||
"https://example.com",
|
|
||||||
"-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
|
|
||||||
"-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----",
|
|
||||||
Instant.now()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
routing {
|
|
||||||
usersAP(mock(), userService, mock(), TestTransaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/users/test") {
|
|
||||||
accept(ContentType.Text.Html)
|
|
||||||
}.let {
|
|
||||||
assertEquals(HttpStatusCode.OK, it.status)
|
|
||||||
assertTrue(it.contentType()?.match(ContentType.Text.Plain) == true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,734 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing.api.internal.v1
|
|
||||||
|
|
||||||
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.Visibility
|
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
|
||||||
import dev.usbharu.hideout.plugins.configureSecurity
|
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
|
||||||
import dev.usbharu.hideout.service.api.PostApiService
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.client.statement.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.server.auth.*
|
|
||||||
import io.ktor.server.auth.jwt.*
|
|
||||||
import io.ktor.server.config.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
import io.ktor.server.testing.*
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.mockito.kotlin.*
|
|
||||||
import utils.JsonObjectMapper
|
|
||||||
import java.time.Instant
|
|
||||||
import kotlin.test.assertContentEquals
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class PostsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun 認証情報無しでpostsにGETしたらPUBLICな投稿一覧が返ってくる() = testApplication {
|
|
||||||
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(
|
|
||||||
PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "test1",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
user = user,
|
|
||||||
text = "test2",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking {
|
|
||||||
getAll(
|
|
||||||
since = anyOrNull(),
|
|
||||||
until = anyOrNull(),
|
|
||||||
minId = anyOrNull(),
|
|
||||||
maxId = anyOrNull(),
|
|
||||||
limit = anyOrNull(),
|
|
||||||
userId = isNull()
|
|
||||||
)
|
|
||||||
} doReturn posts
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/posts").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertContentEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun 認証情報ありでpostsにGETすると権限のある投稿が返ってくる() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
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(
|
|
||||||
PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "test1",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
user = user,
|
|
||||||
text = "test2",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "1234567",
|
|
||||||
user = user,
|
|
||||||
text = "Followers only",
|
|
||||||
visibility = Visibility.FOLLOWERS,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/3"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking {
|
|
||||||
getAll(
|
|
||||||
since = anyOrNull(),
|
|
||||||
until = anyOrNull(),
|
|
||||||
minId = anyOrNull(),
|
|
||||||
maxId = anyOrNull(),
|
|
||||||
limit = anyOrNull(),
|
|
||||||
userId = isNotNull()
|
|
||||||
)
|
|
||||||
} doReturn posts
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
authentication {
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
configureSerialization()
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/api/internal/v1/posts") {
|
|
||||||
header("Authorization", "Bearer asdkaf")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `posts id にGETしたらPUBLICな投稿を取得できる`() = testApplication {
|
|
||||||
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 post = PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "aaa",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { getById(any(), anyOrNull()) } doReturn post
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/api/internal/v1/posts/1").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `認証情報ありでposts id にGETしたら権限のある投稿を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val post = PostResponse(
|
|
||||||
"12345",
|
|
||||||
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(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { getById(any(), isNotNull()) } doReturn post
|
|
||||||
}
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
val payload = mock<Payload> {
|
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
authentication {
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/api/internal/v1/posts/1") {
|
|
||||||
header("Authorization", "Bearer asdkaf")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `posts-post postsにpostしたら投稿できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
val payload = mock<Payload> {
|
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
|
||||||
}
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { createPost(any(), any()) } doAnswer {
|
|
||||||
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
|
|
||||||
val userId = it.getArgument<Long>(1)
|
|
||||||
PostResponse(
|
|
||||||
id = "123",
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
authentication {
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
println("aaaaaaaaaaaa")
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
configureSerialization()
|
|
||||||
}
|
|
||||||
|
|
||||||
val post = dev.usbharu.hideout.domain.model.hideout.form.Post("test")
|
|
||||||
client.post("/api/internal/v1/posts") {
|
|
||||||
header("Authorization", "Bearer asdkaf")
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(Config.configData.objectMapper.writeValueAsString(post))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals("https://example.com", headers["Location"])
|
|
||||||
}
|
|
||||||
argumentCaptor<dev.usbharu.hideout.domain.model.hideout.form.Post> {
|
|
||||||
verify(postService).createPost(capture(), any())
|
|
||||||
assertEquals(dev.usbharu.hideout.domain.model.hideout.form.Post("test"), firstValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users userId postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
|
||||||
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(
|
|
||||||
PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "test1",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
user = user,
|
|
||||||
text = "test2",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking {
|
|
||||||
getByUser(
|
|
||||||
nameOrId = any(),
|
|
||||||
since = anyOrNull(),
|
|
||||||
until = anyOrNull(),
|
|
||||||
minId = anyOrNull(),
|
|
||||||
maxId = anyOrNull(),
|
|
||||||
limit = anyOrNull(),
|
|
||||||
userId = anyOrNull()
|
|
||||||
)
|
|
||||||
} doReturn posts
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/1/posts").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users username postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
|
||||||
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(
|
|
||||||
PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "test1",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
user = user,
|
|
||||||
text = "test2",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking {
|
|
||||||
getByUser(
|
|
||||||
nameOrId = eq("test1"),
|
|
||||||
since = anyOrNull(),
|
|
||||||
until = anyOrNull(),
|
|
||||||
minId = anyOrNull(),
|
|
||||||
maxId = anyOrNull(),
|
|
||||||
limit = anyOrNull(),
|
|
||||||
userId = anyOrNull()
|
|
||||||
)
|
|
||||||
} doReturn posts
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1/posts").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users username@domain postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
|
||||||
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(
|
|
||||||
PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "test1",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
user = user,
|
|
||||||
text = "test2",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking {
|
|
||||||
getByUser(
|
|
||||||
nameOrId = eq("test1@example.com"),
|
|
||||||
since = anyOrNull(),
|
|
||||||
until = anyOrNull(),
|
|
||||||
minId = anyOrNull(),
|
|
||||||
maxId = anyOrNull(),
|
|
||||||
limit = anyOrNull(),
|
|
||||||
userId = anyOrNull()
|
|
||||||
)
|
|
||||||
} doReturn posts
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1@example.com/posts").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users @username@domain postsにGETしたらユーザーのPUBLICな投稿一覧を取得できる`() = testApplication {
|
|
||||||
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(
|
|
||||||
PostResponse(
|
|
||||||
id = "12345",
|
|
||||||
user = user,
|
|
||||||
text = "test1",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/1"
|
|
||||||
),
|
|
||||||
PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
user = user,
|
|
||||||
text = "test2",
|
|
||||||
visibility = Visibility.PUBLIC,
|
|
||||||
createdAt = Instant.now().toEpochMilli(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking {
|
|
||||||
getByUser(
|
|
||||||
nameOrId = eq("@test1@example.com"),
|
|
||||||
since = anyOrNull(),
|
|
||||||
until = anyOrNull(),
|
|
||||||
minId = anyOrNull(),
|
|
||||||
maxId = anyOrNull(),
|
|
||||||
limit = anyOrNull(),
|
|
||||||
userId = anyOrNull()
|
|
||||||
)
|
|
||||||
} doReturn posts
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/@test1@example.com/posts").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(posts, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name posts id にGETしたらPUBLICな投稿を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val post = PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
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(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test/posts/12345").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users id posts id にGETしたらPUBLICな投稿を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val post = PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
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(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/1/posts/12345").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name posts id にGETしたらUserIdが間違っててもPUBLICな投稿を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val post = PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
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(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/423827849732847/posts/12345").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name posts id にGETしたらuserNameが間違っててもPUBLICな投稿を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val post = PostResponse(
|
|
||||||
id = "123456",
|
|
||||||
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(),
|
|
||||||
url = "https://example.com/posts/2"
|
|
||||||
)
|
|
||||||
val postService = mock<PostApiService> {
|
|
||||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
posts(postService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/invalidUserName/posts/12345").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(post, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,692 +0,0 @@
|
||||||
package dev.usbharu.hideout.routing.api.internal.v1
|
|
||||||
|
|
||||||
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.Acct
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.entity.User
|
|
||||||
import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
|
|
||||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
|
||||||
import dev.usbharu.hideout.plugins.configureSecurity
|
|
||||||
import dev.usbharu.hideout.plugins.configureSerialization
|
|
||||||
import dev.usbharu.hideout.service.api.UserApiService
|
|
||||||
import dev.usbharu.hideout.service.user.UserService
|
|
||||||
import io.ktor.client.request.*
|
|
||||||
import io.ktor.client.statement.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.server.auth.*
|
|
||||||
import io.ktor.server.auth.jwt.*
|
|
||||||
import io.ktor.server.config.*
|
|
||||||
import io.ktor.server.routing.*
|
|
||||||
import io.ktor.server.testing.*
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.mockito.kotlin.*
|
|
||||||
import utils.JsonObjectMapper
|
|
||||||
import java.time.Instant
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
@Suppress("LargeClass")
|
|
||||||
class UsersTest {
|
|
||||||
@Test
|
|
||||||
fun `users にGETするとユーザー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val users = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"12345",
|
|
||||||
"test1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"12343",
|
|
||||||
"tes2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"",
|
|
||||||
"https://example.com/tes2",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
val userService = mock<UserApiService> {
|
|
||||||
onBlocking { findAll(anyOrNull(), anyOrNull()) } doReturn users
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.get("/api/internal/v1/users").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(users, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users にPOSTすると新規ユーザー作成ができる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userCreateDto = UserCreate("test", "XXXXXXX")
|
|
||||||
val userService = mock<UserService> {
|
|
||||||
onBlocking { usernameAlreadyUse(any()) } doReturn false
|
|
||||||
onBlocking { createLocalUser(any()) } doReturn User.of(
|
|
||||||
id = 12345,
|
|
||||||
name = "test",
|
|
||||||
domain = "example.com",
|
|
||||||
screenName = "testUser",
|
|
||||||
description = "test user",
|
|
||||||
password = "XXXXXXX",
|
|
||||||
inbox = "https://example.com/inbox",
|
|
||||||
outbox = "https://example.com/outbox",
|
|
||||||
url = "https://example.com",
|
|
||||||
publicKey = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
|
|
||||||
privateKey = "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----",
|
|
||||||
createdAt = Instant.now()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(userService, mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.post("/api/internal/v1/users") {
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(JsonObjectMapper.objectMapper.writeValueAsString(userCreateDto))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Created, status)
|
|
||||||
assertEquals(
|
|
||||||
"${Config.configData.url}/api/internal/v1/users/${userCreateDto.username}",
|
|
||||||
headers["Location"]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users 既にユーザー名が使用されているときはBadRequestが帰ってくる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userCreateDto = UserCreate("test", "XXXXXXX")
|
|
||||||
val userService = mock<UserService> {
|
|
||||||
onBlocking { usernameAlreadyUse(any()) } doReturn true
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(userService, mock())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.post("/api/internal/v1/users") {
|
|
||||||
contentType(ContentType.Application.Json)
|
|
||||||
setBody(JsonObjectMapper.objectMapper.writeValueAsString(userCreateDto))
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.BadRequest, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name にGETしたらユーザーを取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userResponse = UserResponse(
|
|
||||||
"1234",
|
|
||||||
"test1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findByAcct(any()) } doReturn userResponse
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(userResponse, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users id にGETしたらユーザーを取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userResponse = UserResponse(
|
|
||||||
"1234",
|
|
||||||
"test1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findById(any()) } doReturn userResponse
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/1234").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(userResponse, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name@domain にGETしたらユーザーを取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userResponse = UserResponse(
|
|
||||||
"1234",
|
|
||||||
"test1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findByAcct(any()) } doReturn userResponse
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(userResponse, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users @name@domain にGETしたらユーザーを取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
val userResponse = UserResponse(
|
|
||||||
"1234",
|
|
||||||
"test1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findByAcct(any()) } doReturn userResponse
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(userResponse, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name followers にGETしたらフォロワー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val followers = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"1236",
|
|
||||||
"follower2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findFollowersByAcct(any()) } doReturn followers
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1/followers").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(followers, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name@domain followers にGETしたらフォロワー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val followers = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"1236",
|
|
||||||
"follower2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findFollowersByAcct(any()) } doReturn followers
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/@test1@example.com/followers").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(followers, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users id followers にGETしたらフォロワー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val followers = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"1236",
|
|
||||||
"follower2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findFollowers(any()) } doReturn followers
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/1234/followers").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(followers, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name followers に認証情報ありでGETしたらフォローできる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
val payload = mock<Payload> {
|
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
|
||||||
}
|
|
||||||
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findByAcct(any()) } doReturn UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
onBlocking { follow(any<Acct>(), eq(1234)) } doReturn true
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
authentication {
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.post("/api/internal/v1/users/test1/followers") {
|
|
||||||
header(HttpHeaders.Authorization, "Bearer test")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name followers に認証情報ありでGETしたらフォロー処理受付になることもある`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
val payload = mock<Payload> {
|
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
|
||||||
}
|
|
||||||
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findByAcct(any()) } doReturn UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
onBlocking { follow(any<Acct>(), eq(1234)) } doReturn false
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
authentication {
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.post("/api/internal/v1/users/test1/followers") {
|
|
||||||
header(HttpHeaders.Authorization, "Bearer test")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Accepted, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users id followers に認証情報ありでGETしたらフォロー処理受付になることもある`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val claim = mock<Claim> {
|
|
||||||
on { asLong() } doReturn 1234
|
|
||||||
}
|
|
||||||
val payload = mock<Payload> {
|
|
||||||
on { getClaim(eq("uid")) } doReturn claim
|
|
||||||
}
|
|
||||||
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findById(any()) } doReturn UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
onBlocking { follow(eq(1235), eq(1234)) } doReturn false
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
authentication {
|
|
||||||
bearer(TOKEN_AUTH) {
|
|
||||||
authenticate {
|
|
||||||
JWTPrincipal(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.post("/api/internal/v1/users/1235/followers") {
|
|
||||||
header(HttpHeaders.Authorization, "Bearer test")
|
|
||||||
}.apply {
|
|
||||||
assertEquals(HttpStatusCode.Accepted, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name following にGETしたらフォロイー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val followers = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"1236",
|
|
||||||
"follower2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findFollowingsByAcct(any()) } doReturn followers
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1/following").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(followers, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users name@domain following にGETしたらフォロイー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val followers = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"1236",
|
|
||||||
"follower2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findFollowingsByAcct(any()) } doReturn followers
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/test1@domain/following").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(followers, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `users id following にGETしたらフォロイー一覧を取得できる`() = testApplication {
|
|
||||||
environment {
|
|
||||||
config = ApplicationConfig("empty.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
val followers = listOf(
|
|
||||||
UserResponse(
|
|
||||||
"1235",
|
|
||||||
"follower1",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
),
|
|
||||||
UserResponse(
|
|
||||||
"1236",
|
|
||||||
"follower2",
|
|
||||||
"example.com",
|
|
||||||
"test",
|
|
||||||
"test User",
|
|
||||||
"https://example.com/test",
|
|
||||||
Instant.now().toEpochMilli()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val userApiService = mock<UserApiService> {
|
|
||||||
onBlocking { findFollowings(any()) } doReturn followers
|
|
||||||
}
|
|
||||||
application {
|
|
||||||
configureSerialization()
|
|
||||||
configureSecurity(mock(), mock())
|
|
||||||
routing {
|
|
||||||
route("/api/internal/v1") {
|
|
||||||
users(mock(), userApiService)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.get("/api/internal/v1/users/1234/following").apply {
|
|
||||||
assertEquals(HttpStatusCode.OK, status)
|
|
||||||
assertEquals(followers, JsonObjectMapper.objectMapper.readValue(bodyAsText()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue