mirror of https://github.com/usbharu/Hideout.git
				
				
				
			feat: 投稿フォームを追加
This commit is contained in:
		
							parent
							
								
									1fc6a1fa38
								
							
						
					
					
						commit
						91573c0b2e
					
				|  | @ -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) { | ||||
|  |  | |||
|  | @ -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) | ||||
|             } | ||||
|  |  | |||
|  | @ -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)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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" | ||||
|     } | ||||
| } | ||||
|  | @ -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}" | ||||
|     } | ||||
| } | ||||
|  | @ -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") | ||||
|  | @ -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 | ||||
|  | @ -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} | ||||
|  | @ -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 | ||||
|  | @ -1,10 +1,10 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="en" xmlns:th="http://www.thymeleaf.org"> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <title>Title</title> | ||||
| </head> | ||||
| <body> | ||||
| <div th:fragment="single-simple-actor(actor)"></div> | ||||
| 
 | ||||
| </body> | ||||
| </html> | ||||
|  | @ -8,5 +8,44 @@ | |||
| </head> | ||||
| <body> | ||||
| 
 | ||||
| <noscript> | ||||
|     <div> | ||||
|         <img alt="" height="80px" src="" th:src="${user.iconUrl}" width="80px"> | ||||
|         <div style="display: inline-block"> | ||||
|             <p th:text="${user.screenName}+'('+${user.name}+'@'+${user.domain}+')'"></p> | ||||
|         </div> | ||||
|     </div> | ||||
|     <form action="/publish" method="post" th:action="@{/publish}" th:object="${form}"> | ||||
|         <div> | ||||
|             <label for="stats-form-overview" th:text="#{post-form.new-posts-cw}" | ||||
|                    th:title="#{post-form.new-posts-cw-title}" | ||||
|                    title="Add content warning">CW</label> | ||||
|             <input id="stats-form-overview" name="overview" type="text"> | ||||
|         </div> | ||||
|         <div> | ||||
|             <label for="status-form" th:text="#{post-form.new-posts-form-label}">What's on your mind?</label> | ||||
|             <br> | ||||
|             <textarea cols="33" id="status-form" name="status" rows="5"></textarea> | ||||
|         </div> | ||||
|         <div> | ||||
|             <fieldset> | ||||
|                 <legend th:text="#{common.visibility}">Visibility</legend> | ||||
|                 <label for="status-form-visibility-public" th:text="#{common.visibility-public}">Public</label> | ||||
|                 <input id="status-form-visibility-public" name="visibility" th:checked="${form.visibility == 'PUBLIC'}" type="radio" | ||||
|                        value="PUBLIC"> | ||||
|                 <label for="status-form-visibility-unlisted" th:text="#{common.visibility-unlisted}">Unlisted</label> | ||||
|                 <input id="status-form-visibility-unlisted" name="visibility" th:checked="${form.visibility == 'UNLISTED'}" type="radio" | ||||
|                        value="UNLISTED"> | ||||
|                 <label for="status-form-visibility-followers" th:text="#{common.visibility-followers}">Followers</label> | ||||
|                 <input id="status-form-visibility-followers" name="visibility" th:checked="${form.visibility == 'FOLLOWERS'}" type="radio" | ||||
|                        value="FOLLOWERS"> | ||||
|             </fieldset> | ||||
|         </div> | ||||
|         <div> | ||||
|             <input th:value="#{post-form.new-posts-submit}" type="submit" value="Publish!"> | ||||
|         </div> | ||||
|     </form> | ||||
| </noscript> | ||||
| 
 | ||||
| </body> | ||||
| </html> | ||||
		Loading…
	
		Reference in New Issue