From 5a7a4c0bb982ce0d697b04ae172d62033894105c Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sun, 12 Nov 2023 17:24:56 +0900 Subject: [PATCH] =?UTF-8?q?test:=20=E3=83=95=E3=82=A9=E3=83=AD=E3=83=AF?= =?UTF-8?q?=E3=83=BC=E3=81=8C=E3=83=95=E3=82=A9=E3=83=AD=E3=83=AF=E3=83=BC?= =?UTF-8?q?=E9=99=90=E5=AE=9A=E6=8A=95=E7=A8=BF=E3=81=AE=E5=8F=96=E5=BE=97?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/activitypub/note/NoteTest.kt | 63 +++++++++++++++++++ ...WithHttpSignatureSecurityContextFactory.kt | 33 +++++----- ...でフォロワーがfollowers投稿を取得できる.sql | 29 +++++++++ ...証でフォロワーがpublic投稿を取得できる.sql | 29 +++++++++ ...でフォロワーがunlisted投稿を取得できる.sql | 29 +++++++++ 5 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql create mode 100644 src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql create mode 100644 src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql diff --git a/src/intTest/kotlin/activitypub/note/NoteTest.kt b/src/intTest/kotlin/activitypub/note/NoteTest.kt index ca132975..e0433c9f 100644 --- a/src/intTest/kotlin/activitypub/note/NoteTest.kt +++ b/src/intTest/kotlin/activitypub/note/NoteTest.kt @@ -16,6 +16,7 @@ import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.transaction.annotation.Transactional import org.springframework.web.context.WebApplicationContext +import util.WithHttpSignature @SpringBootTest(classes = [SpringApplication::class]) @AutoConfigureMockMvc @@ -88,4 +89,66 @@ class NoteTest { .asyncDispatch() .andExpect { status { isNotFound() } } } + + @Test + @Sql("/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql") + @WithHttpSignature(keyId = "https://follower.example.com/users/test-user5#pubkey") + fun HttpSignature認証でフォロワーがpublic投稿を取得できる() { + mockMvc + .get("/users/test-user4/posts/1237") { + accept(MediaType("application", "activity+json")) + } + .asyncDispatch() + .andDo { print() } + .andExpect { status { isOk() } } + .andExpect { content { contentType("application/activity+json") } } + .andExpect { jsonPath("\$.type") { value("Note") } } + .andExpect { jsonPath("\$.to") { value("https://www.w3.org/ns/activitystreams#Public") } } + .andExpect { jsonPath("\$.cc") { value("https://www.w3.org/ns/activitystreams#Public") } } + } + + @Test + @Sql("/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql") + @WithHttpSignature(keyId = "https://follower.example.com/users/test-user7#pubkey") + fun httpSignature認証でフォロワーがunlisted投稿を取得できる() { + mockMvc + .get("/users/test-user6/posts/1238") { + accept(MediaType("application", "activity+json")) + } + .asyncDispatch() + .andDo { print() } + .andExpect { status { isOk() } } + .andExpect { content { contentType("application/activity+json") } } + .andExpect { jsonPath("\$.type") { value("Note") } } + .andExpect { jsonPath("\$.to") { value("https://example.com/users/test-user6/followers") } } + .andExpect { jsonPath("\$.cc") { value("https://www.w3.org/ns/activitystreams#Public") } } + } + + @Test + @Sql("/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql") + @WithHttpSignature(keyId = "https://follower.example.com/users/test-user9#pubkey") + fun httpSignature認証でフォロワーがfollowers投稿を取得できる() { + mockMvc + .get("/users/test-user8/posts/1239") { + accept(MediaType("application", "activity+json")) + } + .asyncDispatch() + .andDo { print() } + .andExpect { status { isOk() } } + .andExpect { content { contentType("application/activity+json") } } + .andExpect { jsonPath("\$.type") { value("Note") } } + .andExpect { jsonPath("\$.to") { value("https://example.com/users/test-user8/followers") } } + .andExpect { jsonPath("\$.cc") { value("https://example.com/users/test-user8/followers") } } + + } + + @Test + fun リプライになっている投稿はinReplyToが存在する() { + + } + + @Test + fun メディア付き投稿はattachmentにDocumentとして画像が存在する() { + + } } diff --git a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt index 6f73f4df..9108e357 100644 --- a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt +++ b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt @@ -1,14 +1,12 @@ package util import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUserDetailsService +import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.httpsignature.common.HttpHeaders import dev.usbharu.httpsignature.common.HttpMethod import dev.usbharu.httpsignature.common.HttpRequest -import dev.usbharu.httpsignature.sign.RsaSha256HttpSignatureSigner -import dev.usbharu.httpsignature.verify.DefaultSignatureHeaderParser -import dev.usbharu.httpsignature.verify.RsaSha256HttpSignatureVerifier +import kotlinx.coroutines.runBlocking import org.springframework.security.core.context.SecurityContext import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.test.context.support.WithSecurityContextFactory @@ -16,32 +14,35 @@ import org.springframework.security.web.authentication.preauth.PreAuthenticatedA import java.net.URL class WithHttpSignatureSecurityContextFactory( - userQueryService: UserQueryService, - transaction: Transaction + private val userQueryService: UserQueryService, + private val transaction: Transaction ) : WithSecurityContextFactory { private val securityContextStrategy = SecurityContextHolder.getContextHolderStrategy() - private val httpSignatureUserDetailsService: HttpSignatureUserDetailsService = HttpSignatureUserDetailsService( - userQueryService, - RsaSha256HttpSignatureVerifier(DefaultSignatureHeaderParser(), RsaSha256HttpSignatureSigner()), - transaction - ) - - - override fun createSecurityContext(annotation: WithHttpSignature): SecurityContext { + override fun createSecurityContext(annotation: WithHttpSignature): SecurityContext = runBlocking { val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken( annotation.keyId, HttpRequest( URL("https://example.com/inbox"), HttpHeaders(mapOf()), HttpMethod.GET ) ) - val httpSignatureUser = httpSignatureUserDetailsService.loadUserDetails(preAuthenticatedAuthenticationToken) + val httpSignatureUser = transaction.transaction { + val findByKeyId = userQueryService.findByKeyId(annotation.keyId) + HttpSignatureUser( + findByKeyId.name, + findByKeyId.domain, + findByKeyId.id, + true, + true, + mutableListOf() + ) + } preAuthenticatedAuthenticationToken.details = httpSignatureUser preAuthenticatedAuthenticationToken.isAuthenticated = true val emptyContext = securityContextStrategy.createEmptyContext() emptyContext.authentication = preAuthenticatedAuthenticationToken - return emptyContext + return@runBlocking emptyContext } } diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql new file mode 100644 index 00000000..f1a91192 --- /dev/null +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql @@ -0,0 +1,29 @@ +insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, + CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS) +VALUES (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test-user8.', + '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', + 'https://example.com/users/test-user8/inbox', + 'https://example.com/users/test-user8/outbox', 'https://example.com/users/test-user8', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user8#pubkey', 'https://example.com/users/test-user8/following', + 'https://example.com/users/test-user8/followers'); + +insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, + CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS) +VALUES (9, 'test-user9', 'follower.example.com', 'Im test-user9.', 'THis account is test-user9.', + null, + 'https://follower.example.com/users/test-user9/inbox', + 'https://follower.example.com/users/test-user9/outbox', 'https://follower.example.com/users/test-user9', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + null, 12345678, + 'https://follower.example.com/users/test-user9#pubkey', + 'https://follower.example.com/users/test-user9/following', + 'https://follower.example.com/users/test-user9/followers'); + +insert into USERS_FOLLOWERS (USER_ID, FOLLOWER_ID) +VALUES (8, 9); + +insert into POSTS (ID, "userId", OVERVIEW, TEXT, "createdAt", VISIBILITY, URL, "repostId", "replyId", SENSITIVE, AP_ID) +VALUES (1239, 8, null, 'test post', 12345680, 2, 'https://example.com/users/test-user8/posts/1239', null, null, false, + 'https://example.com/users/test-user8/posts/1239'); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql new file mode 100644 index 00000000..20a7e5ba --- /dev/null +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql @@ -0,0 +1,29 @@ +insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, + CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS) +VALUES (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test user4.', + '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', + 'https://example.com/users/test-user4/inbox', + 'https://example.com/users/test-user4/outbox', 'https://example.com/users/test-user4', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user4#pubkey', 'https://example.com/users/test-user4/following', + 'https://example.com/users/test-user4/followers'); + +insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, + CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS) +VALUES (5, 'test-user5', 'follower.example.com', 'Im test user5.', 'THis account is test user5.', + null, + 'https://follower.example.com/users/test-user5/inbox', + 'https://follower.example.com/users/test-user5/outbox', 'https://follower.example.com/users/test-user5', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + null, 12345678, + 'https://follower.example.com/users/test-user5#pubkey', + 'https://follower.example.com/users/test-user5/following', + 'https://follower.example.com/users/test-user5/followers'); + +insert into USERS_FOLLOWERS (USER_ID, FOLLOWER_ID) +VALUES (4, 5); + +insert into POSTS (ID, "userId", OVERVIEW, TEXT, "createdAt", VISIBILITY, URL, "repostId", "replyId", SENSITIVE, AP_ID) +VALUES (1237, 4, null, 'test post', 12345680, 0, 'https://example.com/users/test-user4/posts/1237', null, null, false, + 'https://example.com/users/test-user4/posts/1237'); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql new file mode 100644 index 00000000..cb7707a9 --- /dev/null +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql @@ -0,0 +1,29 @@ +insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, + CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS) +VALUES (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test-user6.', + '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', + 'https://example.com/users/test-user6/inbox', + 'https://example.com/users/test-user6/outbox', 'https://example.com/users/test-user6', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user6#pubkey', 'https://example.com/users/test-user6/following', + 'https://example.com/users/test-user6/followers'); + +insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, + CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS) +VALUES (7, 'test-user7', 'follower.example.com', 'Im test-user7.', 'THis account is test-user7.', + null, + 'https://follower.example.com/users/test-user7/inbox', + 'https://follower.example.com/users/test-user7/outbox', 'https://follower.example.com/users/test-user7', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + null, 12345678, + 'https://follower.example.com/users/test-user7#pubkey', + 'https://follower.example.com/users/test-user7/following', + 'https://follower.example.com/users/test-user7/followers'); + +insert into USERS_FOLLOWERS (USER_ID, FOLLOWER_ID) +VALUES (6, 7); + +insert into POSTS (ID, "userId", OVERVIEW, TEXT, "createdAt", VISIBILITY, URL, "repostId", "replyId", SENSITIVE, AP_ID) +VALUES (1238, 6, null, 'test post', 12345680, 1, 'https://example.com/users/test-user6/posts/1238', null, null, false, + 'https://example.com/users/test-user6/posts/1238');