From 91573c0b2e8949ac0d0a140424bcf2af23ef43cd Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:31:02 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8A=95=E7=A8=BF=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/GetPostDetailApplicationService.kt | 5 +-- .../hideout/core/config/SecurityConfig.kt | 2 + .../post/DefaultPostReadAccessControl.kt | 6 +++ .../interfaces/web/posts/PostsController.kt | 15 +++++-- .../interfaces/web/posts/PublishController.kt | 32 ++++++++++++++- .../core/interfaces/web/posts/PublishPost.kt | 3 ++ .../messages/hideout-web-messages.properties | 8 ++++ .../hideout-web-messages_en_US.properties | 8 ++++ .../hideout-web-messages_ja_JP.properties | 8 ++++ .../resources/templates/fragments-actor.html | 4 +- .../resources/templates/post-postForm.html | 39 +++++++++++++++++++ 11 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/GetPostDetailApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/GetPostDetailApplicationService.kt index 55fcf60e..fcc4ab3d 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/GetPostDetailApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/GetPostDetailApplicationService.kt @@ -1,7 +1,6 @@ package dev.usbharu.hideout.core.application.post import dev.usbharu.hideout.core.application.exception.InternalServerException -import dev.usbharu.hideout.core.application.exception.PermissionDeniedException import dev.usbharu.hideout.core.application.shared.AbstractApplicationService import dev.usbharu.hideout.core.application.shared.Transaction import dev.usbharu.hideout.core.domain.model.actor.Actor @@ -32,7 +31,7 @@ class GetPostDetailApplicationService( val post = postRepository.findById(PostId(command.postId)) ?: throw IllegalArgumentException("Post ${command.postId} not found.") if (iPostReadAccessControl.isAllow(post, principal).not()) { - throw PermissionDeniedException() + throw IllegalArgumentException("Post ${command.postId} not found.") } val actor = actorRepository.findById(post.actorId) ?: throw InternalServerException("Actor ${post.actorId} not found.") @@ -65,7 +64,7 @@ class GetPostDetailApplicationService( val post = postRepository.findById(postId) ?: return null if (iPostReadAccessControl.isAllow(post, principal).not()) { - throw PermissionDeniedException() + return null } val (first, second: Instance, third) = if (actor.id != post.actorId) { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt index 95ce0b6c..ae7504a2 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt @@ -83,6 +83,8 @@ class SecurityConfig { authorize(POST, "/auth/sign_up", permitAll) authorize(GET, "/users/{username}/posts/{postId}", permitAll) authorize(GET, "/files/*", permitAll) + authorize(POST, "/publish", authenticated) + authorize(GET, "/publish", authenticated) authorize(anyRequest, authenticated) } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt index 4e7fba5e..b7274df9 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt @@ -16,6 +16,12 @@ interface IPostReadAccessControl { class DefaultPostReadAccessControl(private val relationshipRepository: RelationshipRepository) : IPostReadAccessControl { override suspend fun isAllow(post: Post, principal: Principal): Boolean { + + //ポスト主は無条件で見れる + if (post.actorId == principal.actorId) { + return true + } + val relationship = (relationshipRepository.findByActorIdAndTargetId(post.actorId, principal.actorId) ?: Relationship.default(post.actorId, principal.actorId)) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PostsController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PostsController.kt index e7092484..7395bfc7 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PostsController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PostsController.kt @@ -1,9 +1,11 @@ package dev.usbharu.hideout.core.interfaces.web.posts +import dev.usbharu.hideout.core.application.exception.PermissionDeniedException import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService import dev.usbharu.hideout.core.application.post.GetPostDetail import dev.usbharu.hideout.core.application.post.GetPostDetailApplicationService import dev.usbharu.hideout.core.infrastructure.springframework.SpringSecurityFormLoginPrincipalContextHolder +import org.springframework.security.access.AccessDeniedException import org.springframework.stereotype.Controller import org.springframework.ui.Model import org.springframework.web.bind.annotation.GetMapping @@ -18,10 +20,15 @@ class PostsController( @GetMapping("/users/{name}/posts/{id}") suspend fun postById(@PathVariable id: Long, model: Model): String { val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() - val post = getPostDetailApplicationService.execute(GetPostDetail(id), principal) - val instance = getLocalInstanceApplicationService.execute(Unit, principal) - model.addAttribute("post", post) - model.addAttribute("instance", instance) + try { + val post = getPostDetailApplicationService.execute(GetPostDetail(id), principal) + val instance = getLocalInstanceApplicationService.execute(Unit, principal) + model.addAttribute("post", post) + model.addAttribute("instance", instance) + } catch (e: PermissionDeniedException) { + throw AccessDeniedException("403 Forbidden", e) + } + return "postById" } } \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt index c3c30076..2c472bf5 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt @@ -3,17 +3,23 @@ package dev.usbharu.hideout.core.interfaces.web.posts import dev.usbharu.hideout.core.application.actor.GetUserDetail import dev.usbharu.hideout.core.application.actor.GetUserDetailApplicationService import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService +import dev.usbharu.hideout.core.application.post.RegisterLocalPost +import dev.usbharu.hideout.core.application.post.RegisterLocalPostApplicationService +import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.infrastructure.springframework.SpringSecurityFormLoginPrincipalContextHolder import org.springframework.security.access.AccessDeniedException import org.springframework.stereotype.Controller import org.springframework.ui.Model import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.ModelAttribute +import org.springframework.web.bind.annotation.PostMapping @Controller class PublishController( private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService, private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder, - private val getUserDetailApplicationService: GetUserDetailApplicationService + private val getUserDetailApplicationService: GetUserDetailApplicationService, + private val userRegisterLocalPostApplicationService: RegisterLocalPostApplicationService ) { @GetMapping("/publish") suspend fun publish(model: Model): String { @@ -26,7 +32,29 @@ class PublishController( val instance = getLocalInstanceApplicationService.execute(Unit, principal) val userDetail = getUserDetailApplicationService.execute(GetUserDetail(principal.userDetailId!!.id), principal) model.addAttribute("instance", instance) - model.addAttribute("user") + model.addAttribute("user", userDetail) + model.addAttribute("form", PublishPost()) return "post-postForm" } + + @PostMapping("/publish") + suspend fun publishForm(@ModelAttribute publishPost: PublishPost): String { + val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() + if (principal.userDetailId == null) { + throw AccessDeniedException("403 Forbidden") + } + + val command = RegisterLocalPost( + content = publishPost.status.orEmpty(), + overview = publishPost.overview, + visibility = Visibility.valueOf(publishPost.visibility.uppercase()), + repostId = null, + replyId = null, + sensitive = false, + mediaIds = emptyList() + ) + val id = userRegisterLocalPostApplicationService.execute(command, principal) + + return "redirect:/users/${principal.acct?.userpart}/posts/${id}" + } } \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt new file mode 100644 index 00000000..c732d2eb --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt @@ -0,0 +1,3 @@ +package dev.usbharu.hideout.core.interfaces.web.posts + +data class PublishPost(var status: String? = null, var overview: String? = null, var visibility: String = "PUBLIC") diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages.properties b/hideout-core/src/main/resources/messages/hideout-web-messages.properties index 92164d8a..6bc6f623 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages.properties @@ -5,7 +5,15 @@ common.thumbnail=\u30B5\u30E0\u30CD\u30A4\u30EB common.unknwon-file-type=\u4E0D\u660E\u306A\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F common.video=\u52D5\u753B common.video-download-link=\u52D5\u753B\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30B5\u30E0\u30CD\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9 +common.visibility=\u516C\u958B\u7BC4\u56F2 +common.visibility-followers=\u30D5\u30A9\u30ED\u30EF\u30FC\u306E\u307F +common.visibility-public=\u30D1\u30D6\u30EA\u30C3\u30AF +common.visibility-unlisted=\u672A\u53CE\u8F09 post-by-id.title={0} \u3055\u3093\u306E\u6295\u7A3F - {1} post-form.new-posts=\u65B0\u3057\u3044\u6295\u7A3F! +post-form.new-posts-cw=CW +post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6CE8\u610F\u3092\u3064\u3051\u308B +post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? +post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties index facd4eed..1f1223cb 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties @@ -5,6 +5,14 @@ common.thumbnail=thumbnail common.unknwon-file-type=Unknown filetype common.video=Video common.video-download-link=Download the Video or thumbnail. +common.visibility=Visibility +common.visibility-followers=Followers only +common.visibility-public=Public +common.visibility-unlisted=Unlisted post-form.new-posts=New Posts! +post-form.new-posts-cw=CW +post-form.new-posts-cw-title=Add content warning +post-form.new-posts-form-label=What's on your mind? +post-form.new-posts-submit=Submit! post.repost=Repost post.repost-by=Repost by {0} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties index 92164d8a..6bc6f623 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties @@ -5,7 +5,15 @@ common.thumbnail=\u30B5\u30E0\u30CD\u30A4\u30EB common.unknwon-file-type=\u4E0D\u660E\u306A\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F common.video=\u52D5\u753B common.video-download-link=\u52D5\u753B\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30B5\u30E0\u30CD\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9 +common.visibility=\u516C\u958B\u7BC4\u56F2 +common.visibility-followers=\u30D5\u30A9\u30ED\u30EF\u30FC\u306E\u307F +common.visibility-public=\u30D1\u30D6\u30EA\u30C3\u30AF +common.visibility-unlisted=\u672A\u53CE\u8F09 post-by-id.title={0} \u3055\u3093\u306E\u6295\u7A3F - {1} post-form.new-posts=\u65B0\u3057\u3044\u6295\u7A3F! +post-form.new-posts-cw=CW +post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6CE8\u610F\u3092\u3064\u3051\u308B +post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? +post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 \ No newline at end of file diff --git a/hideout-core/src/main/resources/templates/fragments-actor.html b/hideout-core/src/main/resources/templates/fragments-actor.html index 829f124b..566549bd 100644 --- a/hideout-core/src/main/resources/templates/fragments-actor.html +++ b/hideout-core/src/main/resources/templates/fragments-actor.html @@ -1,10 +1,10 @@ - + Title -
+ \ No newline at end of file diff --git a/hideout-core/src/main/resources/templates/post-postForm.html b/hideout-core/src/main/resources/templates/post-postForm.html index 1709ce9a..a53bfba4 100644 --- a/hideout-core/src/main/resources/templates/post-postForm.html +++ b/hideout-core/src/main/resources/templates/post-postForm.html @@ -8,5 +8,44 @@ + + \ No newline at end of file