From a732031b7e45a23cdf0a25a6bbdbb53ca733abf5 Mon Sep 17 00:00:00 2001 From: jaejae-yoo Date: Fri, 12 Aug 2022 16:22:04 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor:=20ArticleController=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20PathVariable=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Controller.java => ArticleController.java} | 31 +++-- .../moamoa/community/domain/Article.java | 10 ++ ...rticleService.java => ArticleService.java} | 13 +- .../test/notice/NoticeAcceptanceTest.java | 121 ++++++++++++++++++ ...erTest.java => ArticleControllerTest.java} | 16 ++- ...ava => DeletingArticleControllerTest.java} | 27 ++-- ...java => GettingArticleControllerTest.java} | 27 ++-- ...mmunityArticleSummariesControllerTest.java | 31 ++--- ...ava => UpdatingArticleControllerTest.java} | 28 ++-- ... CreatingArticleControllerWebMvcTest.java} | 8 +- ... DeletingArticleControllerWebMvcTest.java} | 2 +- ...> GettingArticleControllerWebMvcTest.java} | 2 +- ... UpdatingArticleControllerWebMvcTest.java} | 2 +- 13 files changed, 218 insertions(+), 100 deletions(-) rename backend/src/main/java/com/woowacourse/moamoa/community/controller/{CommunityArticleController.java => ArticleController.java} (71%) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java rename backend/src/main/java/com/woowacourse/moamoa/community/service/{CommunityArticleService.java => ArticleService.java} (88%) create mode 100644 backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java rename backend/src/test/java/com/woowacourse/moamoa/community/controller/{CommunityArticleControllerTest.java => ArticleControllerTest.java} (90%) rename backend/src/test/java/com/woowacourse/moamoa/community/controller/{DeletingCommunityArticleControllerTest.java => DeletingArticleControllerTest.java} (77%) rename backend/src/test/java/com/woowacourse/moamoa/community/controller/{GettingCommunityArticleControllerTest.java => GettingArticleControllerTest.java} (81%) rename backend/src/test/java/com/woowacourse/moamoa/community/controller/{UpdatingCommunityArticleControllerTest.java => UpdatingArticleControllerTest.java} (79%) rename backend/src/test/java/com/woowacourse/moamoa/community/webmvc/{CreatingCommunityArticleControllerWebMvcTest.java => CreatingArticleControllerWebMvcTest.java} (95%) rename backend/src/test/java/com/woowacourse/moamoa/community/webmvc/{DeletingCommunityArticleControllerWebMvcTest.java => DeletingArticleControllerWebMvcTest.java} (96%) rename backend/src/test/java/com/woowacourse/moamoa/community/webmvc/{GettingCommunityArticleControllerWebMvcTest.java => GettingArticleControllerWebMvcTest.java} (98%) rename backend/src/test/java/com/woowacourse/moamoa/community/webmvc/{UpdatingCommunityArticleControllerWebMvcTest.java => UpdatingArticleControllerWebMvcTest.java} (98%) diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/controller/CommunityArticleController.java b/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java similarity index 71% rename from backend/src/main/java/com/woowacourse/moamoa/community/controller/CommunityArticleController.java rename to backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java index ca9fe0ef9..c8ca5d8ae 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/controller/CommunityArticleController.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java @@ -1,9 +1,8 @@ package com.woowacourse.moamoa.community.controller; import com.woowacourse.moamoa.auth.config.AuthenticatedMember; -import com.woowacourse.moamoa.auth.config.AuthenticationPrincipal; import com.woowacourse.moamoa.community.domain.CommunityArticle; -import com.woowacourse.moamoa.community.service.CommunityArticleService; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.community.service.response.ArticleResponse; import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; @@ -23,21 +22,21 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("api/studies/{study-id}/community/articles") -public class CommunityArticleController { +@RequestMapping("api/studies/{study-id}/{article-type}/articles") +public class ArticleController { - private final CommunityArticleService communityArticleService; + private final ArticleService articleService; - public CommunityArticleController(final CommunityArticleService communityArticleService) { - this.communityArticleService = communityArticleService; + public ArticleController(final ArticleService articleService) { + this.articleService = articleService; } @PostMapping public ResponseEntity createArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, - @Valid @RequestBody final ArticleRequest request - ) { - final CommunityArticle article = communityArticleService.createArticle(id, studyId, request); + @PathVariable("article-type") final String articleType, + @Valid @RequestBody final ArticleRequest request) { + final CommunityArticle article = articleService.createArticle(id, studyId, request); final URI location = URI.create("/api/studies/" + studyId + "/community/articles/" + article.getId()); return ResponseEntity.created(location).header("Access-Control-Allow-Headers", HttpHeaders.LOCATION).build(); } @@ -45,37 +44,41 @@ public ResponseEntity createArticle(@AuthenticatedMember final Long id, @GetMapping("/{article-id}") public ResponseEntity getArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, + @PathVariable("article-type") final String articleType, @PathVariable("article-id") final Long articleId ) { - ArticleResponse response = communityArticleService.getArticle(id, studyId, articleId); + ArticleResponse response = articleService.getArticle(id, studyId, articleId); return ResponseEntity.ok().body(response); } @DeleteMapping("{article-id}") public ResponseEntity deleteArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, + @PathVariable("article-type") final String articleType, @PathVariable("article-id") final Long articleId ) { - communityArticleService.deleteArticle(id, studyId, articleId); + articleService.deleteArticle(id, studyId, articleId); return ResponseEntity.noContent().build(); } @GetMapping public ResponseEntity getArticles(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, + @PathVariable("article-type") final String articleType, @PageableDefault final Pageable pageable ) { - ArticleSummariesResponse response = communityArticleService.getArticles(id, studyId, pageable); + ArticleSummariesResponse response = articleService.getArticles(id, studyId, pageable); return ResponseEntity.ok().body(response); } @PutMapping("/{article-id}") public ResponseEntity updateArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, + @PathVariable("article-type") final String articleType, @PathVariable("article-id") final Long articleId, @Valid @RequestBody final ArticleRequest request ) { - communityArticleService.updateArticle(id, studyId, articleId, request); + articleService.updateArticle(id, studyId, articleId, request); return ResponseEntity.noContent().build(); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java new file mode 100644 index 000000000..9ac3673d8 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java @@ -0,0 +1,10 @@ +package com.woowacourse.moamoa.community.domain; + +public interface Article { + + void update(final String title, final String content); + + boolean isViewableBy(final Long studyId, final Long memberId); + + boolean isEditableBy(final Long studyId, final Long memberId); +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/CommunityArticleService.java b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java similarity index 88% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/CommunityArticleService.java rename to backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java index b4b272591..31ca6f5f9 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/CommunityArticleService.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java @@ -5,8 +5,6 @@ import com.woowacourse.moamoa.community.query.CommunityArticleDao; import com.woowacourse.moamoa.community.query.data.CommunityArticleData; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.NotArticleAuthorException; -import com.woowacourse.moamoa.community.service.exception.NotRelatedArticleException; import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; import com.woowacourse.moamoa.community.service.request.ArticleRequest; @@ -16,7 +14,6 @@ import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; @@ -29,17 +26,17 @@ @Service @Transactional(readOnly = true) -public class CommunityArticleService { +public class ArticleService { private final MemberRepository memberRepository; private final StudyRepository studyRepository; private final CommunityArticleRepository communityArticleRepository; private final CommunityArticleDao communityArticleDao; - public CommunityArticleService(final MemberRepository memberRepository, - final StudyRepository studyRepository, - final CommunityArticleRepository communityArticleRepository, - final CommunityArticleDao communityArticleDao) { + public ArticleService(final MemberRepository memberRepository, + final StudyRepository studyRepository, + final CommunityArticleRepository communityArticleRepository, + final CommunityArticleDao communityArticleDao) { this.memberRepository = memberRepository; this.studyRepository = studyRepository; this.communityArticleRepository = communityArticleRepository; diff --git a/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java b/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java new file mode 100644 index 000000000..5b3a8c693 --- /dev/null +++ b/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java @@ -0,0 +1,121 @@ +package com.woowacourse.acceptance.test.notice; + +import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_깃허브_ID; +import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이름; +import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이미지_URL; +import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_프로필_URL; +import static com.woowacourse.acceptance.steps.LoginSteps.그린론이; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; + +import com.woowacourse.acceptance.AcceptanceTest; +import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.community.service.response.ArticleResponse; +import com.woowacourse.moamoa.community.service.response.AuthorResponse; +import io.restassured.RestAssured; +import java.time.LocalDate; +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +public class NoticeAcceptanceTest extends AcceptanceTest { + + @DisplayName("스터디에 공지사항을 작성한다.") + @Test + void writeNotice() throws Exception { + // arrange + long 스터디_ID = 그린론이().로그인하고().자바_스터디를().시작일자는(LocalDate.now()).생성한다(); + String 토큰 = 그린론이().로그인한다(); + ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); + + // act + final String location = RestAssured.given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .body(objectMapper.writeValueAsString(request)) + .pathParam("study-id", 스터디_ID) + .when().log().all() + .filter(document("write/notice", + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("JWT 토큰") + ), + pathParameters( + parameterWithName("study-id").description("스터디 식별 ID") + ), + requestFields( + fieldWithPath("title").type(JsonFieldType.STRING).description("공지사항 제목"), + fieldWithPath("content").type(JsonFieldType.STRING).description("공지사항 내용") + ), + responseHeaders( + headerWithName(HttpHeaders.LOCATION).description("생성된 공지사항 url"), + headerWithName("Access-Control-Allow-Headers").description("접근 가능한 헤더") + )) + ) + .post("/api/studies/{study-id}/notice/articles") + .then().log().all() + .statusCode(HttpStatus.CREATED.value()) + .extract() + .header(HttpHeaders.LOCATION); + + // assert + Long articleId = Long.valueOf(location.split("/")[6]); + + final ArticleResponse actualResponse = RestAssured + .given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .pathParam("study-id", 스터디_ID) + .pathParam("article-id", articleId) + .filter(document("get/notice", + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("JWT 토큰") + ), + pathParameters( + parameterWithName("study-id").description("스터디 식별 ID"), + parameterWithName("article-id").description("공지사항 식별 ID") + ), + responseFields( + fieldWithPath("id").type(JsonFieldType.NUMBER).description("공지사항 식별 ID"), + fieldWithPath("author").type(JsonFieldType.OBJECT).description("작성자"), + fieldWithPath("author.id").type(JsonFieldType.NUMBER).description("작성자 github ID"), + fieldWithPath("author.username").type(JsonFieldType.STRING) + .description("작성자 github 사용자 이름"), + fieldWithPath("author.imageUrl").type(JsonFieldType.STRING) + .description("작성자 github 이미지 URL"), + fieldWithPath("author.profileUrl").type(JsonFieldType.STRING) + .description("작성자 github 프로필 URL"), + fieldWithPath("title").type(JsonFieldType.STRING).description("공지사항 제목"), + fieldWithPath("content").type(JsonFieldType.STRING).description("공지사항 내용"), + fieldWithPath("createdDate").type(JsonFieldType.STRING).description("공지사항 작성일"), + fieldWithPath("lastModifiedDate").type(JsonFieldType.STRING).description("공지사항 수정일") + ) + )) + .when().log().all() + .get("/api/studies/{study-id}/notice/articles/{article-id}") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract().as(ArticleResponse.class); + + final ArticleResponse expectedResponse = ArticleResponse.builder() + .id(articleId) + .author(new AuthorResponse(그린론_깃허브_ID, 그린론_이름, 그린론_이미지_URL, 그린론_프로필_URL)) + .title("공지사항 제목") + .content("공지사항 내용") + .createdDate(LocalDate.now()) + .lastModifiedDate(LocalDate.now()) + .build(); + + assertThat(actualResponse).isEqualTo(expectedResponse); + } +} diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/CommunityArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java similarity index 90% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/CommunityArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java index 05a187dd4..e115853a9 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/CommunityArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java @@ -8,7 +8,7 @@ import com.woowacourse.moamoa.community.domain.CommunityArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; import com.woowacourse.moamoa.community.query.CommunityArticleDao; -import com.woowacourse.moamoa.community.service.CommunityArticleService; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; @@ -27,7 +27,7 @@ import org.springframework.http.ResponseEntity; @RepositoryTest -public class CommunityArticleControllerTest { +public class ArticleControllerTest { CreatingStudyRequestBuilder javaStudyRequest = new CreatingStudyRequestBuilder() .title("java 스터디").excerpt("자바 설명").thumbnail("java image").description("자바 소개"); @@ -45,12 +45,12 @@ public class CommunityArticleControllerTest { private CommunityArticleDao communityArticleDao; private StudyService studyService; - private CommunityArticleController sut; + private ArticleController sut; @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - sut = new CommunityArticleController(new CommunityArticleService(memberRepository, studyRepository, + sut = new ArticleController(new ArticleService(memberRepository, studyRepository, communityArticleRepository, communityArticleDao)); } @@ -65,7 +65,7 @@ void createCommunityArticle() { ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); // act - ResponseEntity response = sut.createArticle(member.getId(), study.getId(), request); + ResponseEntity response = sut.createArticle(member.getId(), study.getId(), "community", request); // assert String location = response.getHeaders().getLocation().getPath(); @@ -86,7 +86,9 @@ void throwExceptionWhenCreateByNotFoundMember() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.createArticle(member.getId() + 1, study.getId(), new ArticleRequest("제목", "내용"))) + assertThatThrownBy(() -> sut.createArticle(member.getId() + 1, study.getId(), "community", + new ArticleRequest("제목", "내용") + )) .isInstanceOf(MemberNotFoundException.class); } @@ -97,7 +99,7 @@ void throwExceptionWhenWriteToNotFoundStudy() { Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); // act & assert - assertThatThrownBy(() -> sut.createArticle(member.getId(), 1L, new ArticleRequest("제목", "내용"))) + assertThatThrownBy(() -> sut.createArticle(member.getId(), 1L, "community", new ArticleRequest("제목", "내용"))) .isInstanceOf(StudyNotFoundException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingCommunityArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java similarity index 77% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingCommunityArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java index 3778aaa87..5c482caca 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingCommunityArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java @@ -8,20 +8,15 @@ import com.woowacourse.moamoa.community.domain.CommunityArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; import com.woowacourse.moamoa.community.query.CommunityArticleDao; -import com.woowacourse.moamoa.community.service.CommunityArticleService; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.NotArticleAuthorException; -import com.woowacourse.moamoa.community.service.exception.NotRelatedArticleException; import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; -import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import java.time.LocalDate; import org.junit.jupiter.api.BeforeEach; @@ -30,7 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; @RepositoryTest -public class DeletingCommunityArticleControllerTest { +public class DeletingArticleControllerTest { CreatingStudyRequestBuilder javaStudyRequest = new CreatingStudyRequestBuilder() .title("java 스터디").excerpt("자바 설명").thumbnail("java image").description("자바 소개"); @@ -48,15 +43,15 @@ public class DeletingCommunityArticleControllerTest { private CommunityArticleDao communityArticleDao; private StudyService studyService; - private CommunityArticleController sut; - private CommunityArticleService communityArticleService; + private ArticleController sut; + private ArticleService articleService; @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - communityArticleService = new CommunityArticleService(memberRepository, studyRepository, + articleService = new ArticleService(memberRepository, studyRepository, communityArticleRepository, communityArticleDao); - sut = new CommunityArticleController(communityArticleService); + sut = new ArticleController(articleService); } @DisplayName("스터디 커뮤니티 게시글을 삭제한다.") @@ -69,11 +64,11 @@ void deleteCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - CommunityArticle article = communityArticleService.createArticle(member.getId(), study.getId(), + CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), request); //act - sut.deleteArticle(member.getId(), study.getId(), article.getId()); + sut.deleteArticle(member.getId(), study.getId(), "community", article.getId()); //assert assertThat(communityArticleRepository.existsById(article.getId())).isFalse(); @@ -88,7 +83,7 @@ void throwExceptionWhenGettingToNotFoundArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.deleteArticle(member.getId(), study.getId(), 1L)) + assertThatThrownBy(() -> sut.deleteArticle(member.getId(), study.getId(), "community", 1L)) .isInstanceOf(ArticleNotFoundException.class); } @@ -103,11 +98,11 @@ void throwExceptionWhenDeletingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = communityArticleService.createArticle(member.getId(), study.getId(), + final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), request); // act & assert - assertThatThrownBy(() -> sut.deleteArticle(other.getId(), study.getId(), article.getId())) + assertThatThrownBy(() -> sut.deleteArticle(other.getId(), study.getId(), "community", article.getId())) .isInstanceOf(UneditableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java similarity index 81% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java index 24e9bfffd..7174c062b 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java @@ -8,24 +8,19 @@ import com.woowacourse.moamoa.community.domain.CommunityArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; import com.woowacourse.moamoa.community.query.CommunityArticleDao; -import com.woowacourse.moamoa.community.service.CommunityArticleService; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.NotRelatedArticleException; import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.community.service.response.ArticleResponse; import com.woowacourse.moamoa.community.service.response.AuthorResponse; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; -import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import java.time.LocalDate; -import javax.persistence.EntityManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -34,7 +29,7 @@ import org.springframework.http.ResponseEntity; @RepositoryTest -public class GettingCommunityArticleControllerTest { +public class GettingArticleControllerTest { CreatingStudyRequestBuilder javaStudyRequest = new CreatingStudyRequestBuilder() .title("java 스터디").excerpt("자바 설명").thumbnail("java image").description("자바 소개"); @@ -52,15 +47,15 @@ public class GettingCommunityArticleControllerTest { private CommunityArticleDao communityArticleDao; private StudyService studyService; - private CommunityArticleController sut; - private CommunityArticleService communityArticleService; + private ArticleController sut; + private ArticleService articleService; @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - communityArticleService = new CommunityArticleService(memberRepository, studyRepository, + articleService = new ArticleService(memberRepository, studyRepository, communityArticleRepository, communityArticleDao); - sut = new CommunityArticleController(communityArticleService); + sut = new ArticleController(articleService); } @DisplayName("스터디 게시글을 단건 조회한다.") @@ -72,12 +67,12 @@ void getStudyCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = communityArticleService.createArticle(member.getId(), study.getId(), + final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), request); //act final ResponseEntity response = sut.getArticle(member.getId(), study.getId(), - article.getId()); + "community", article.getId()); //assert assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -96,7 +91,7 @@ void throwExceptionWhenGettingToNotFoundArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.getArticle(member.getId(), study.getId(), 1L)) + assertThatThrownBy(() -> sut.getArticle(member.getId(), study.getId(), "community", 1L)) .isInstanceOf(ArticleNotFoundException.class); } @@ -111,11 +106,11 @@ void throwExceptionWhenGettingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = communityArticleService.createArticle(member.getId(), study.getId(), + final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), request); // act & assert - assertThatThrownBy(() -> sut.getArticle(other.getId(), study.getId(), article.getId())) + assertThatThrownBy(() -> sut.getArticle(other.getId(), study.getId(), "community", article.getId())) .isInstanceOf(UnviewableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java index 54ba3455a..5a5657a41 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java @@ -8,8 +8,7 @@ import com.woowacourse.moamoa.community.domain.CommunityArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; import com.woowacourse.moamoa.community.query.CommunityArticleDao; -import com.woowacourse.moamoa.community.service.CommunityArticleService; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; @@ -17,14 +16,11 @@ import com.woowacourse.moamoa.community.service.response.AuthorResponse; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; -import java.lang.reflect.Field; import java.time.LocalDate; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -41,7 +37,7 @@ public class GettingCommunityArticleSummariesControllerTest { CreatingStudyRequestBuilder javaStudyRequest = new CreatingStudyRequestBuilder() .title("java 스터디").excerpt("자바 설명").thumbnail("java image").description("자바 소개"); - private CommunityArticleService communityArticleService; + private ArticleService articleService; private StudyService studyService; @@ -57,14 +53,14 @@ public class GettingCommunityArticleSummariesControllerTest { @Autowired private CommunityArticleDao communityArticleDao; - private CommunityArticleController sut; + private ArticleController sut; @BeforeEach void setUp() { - communityArticleService = new CommunityArticleService(memberRepository, studyRepository, + articleService = new ArticleService(memberRepository, studyRepository, communityArticleRepository, communityArticleDao); studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - sut = new CommunityArticleController(communityArticleService); + sut = new ArticleController(articleService); } @DisplayName("스터디 커뮤니티 글 목록을 조회한다.") @@ -75,17 +71,18 @@ void getCommunityArticles() { Study study = studyService.createStudy(그린론.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); - communityArticleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목1", "내용1")); - communityArticleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목2", "내용2")); - CommunityArticle article3 = communityArticleService + articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목1", "내용1")); + articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목2", "내용2")); + CommunityArticle article3 = articleService .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목3", "내용3")); - CommunityArticle article4 = communityArticleService + CommunityArticle article4 = articleService .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목4", "내용4")); - CommunityArticle article5 = communityArticleService + CommunityArticle article5 = articleService .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목5", "내용5")); // act - ResponseEntity response = sut.getArticles(그린론.getId(), study.getId(), PageRequest.of(0, 3)); + ResponseEntity response = sut.getArticles(그린론.getId(), study.getId(), "community", + PageRequest.of(0, 3)); // assert AuthorResponse author = new AuthorResponse(1L, "그린론", "http://image", "http://profile"); @@ -109,7 +106,7 @@ void throwExceptionWhenWriteToNotFoundStudy() { Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); // act & assert - assertThatThrownBy(() -> sut.getArticles(member.getId(), 1L, PageRequest.of(0, 3))) + assertThatThrownBy(() -> sut.getArticles(member.getId(), 1L, "community", PageRequest.of(0, 3))) .isInstanceOf(StudyNotFoundException.class); } @@ -124,7 +121,7 @@ void throwExceptionWhenGettingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.getArticles(other.getId(), study.getId(), PageRequest.of(0, 3))) + assertThatThrownBy(() -> sut.getArticles(other.getId(), study.getId(), "community", PageRequest.of(0, 3))) .isInstanceOf(UnviewableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingCommunityArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java similarity index 79% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingCommunityArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java index ea0d3cacd..080c1b046 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingCommunityArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java @@ -8,19 +8,15 @@ import com.woowacourse.moamoa.community.domain.CommunityArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; import com.woowacourse.moamoa.community.query.CommunityArticleDao; -import com.woowacourse.moamoa.community.service.CommunityArticleService; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.NotArticleAuthorException; -import com.woowacourse.moamoa.community.service.exception.NotRelatedArticleException; import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; -import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import java.time.LocalDate; import org.junit.jupiter.api.BeforeEach; @@ -31,7 +27,7 @@ import org.springframework.http.ResponseEntity; @RepositoryTest -public class UpdatingCommunityArticleControllerTest { +public class UpdatingArticleControllerTest { CreatingStudyRequestBuilder javaStudyBuilder = new CreatingStudyRequestBuilder() .title("java 스터디").excerpt("자바 설명").thumbnail("java image").description("자바 소개"); @@ -49,15 +45,15 @@ public class UpdatingCommunityArticleControllerTest { private CommunityArticleDao communityArticleDao; private StudyService studyService; - private CommunityArticleController sut; - private CommunityArticleService communityArticleService; + private ArticleController sut; + private ArticleService articleService; @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - communityArticleService = new CommunityArticleService(memberRepository, studyRepository, + articleService = new ArticleService(memberRepository, studyRepository, communityArticleRepository, communityArticleDao); - sut = new CommunityArticleController(communityArticleService); + sut = new ArticleController(articleService); } @DisplayName("게시글을 수정한다.") @@ -67,11 +63,11 @@ void updateArticle() { Member member = memberRepository.save(new Member(1L, "username", "image", "profile")); Study study = studyService .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); - CommunityArticle article = communityArticleService + CommunityArticle article = articleService .createArticle(member.getId(), study.getId(), new ArticleRequest("제목", "내용")); // act - final ResponseEntity response = sut.updateArticle(member.getId(), study.getId(), article.getId(), + final ResponseEntity response = sut.updateArticle(member.getId(), study.getId(), "community", article.getId(), new ArticleRequest("제목 수정", "내용 수정")); // assert @@ -92,7 +88,8 @@ void throwExceptionWhenUpdateToNotFoundArticle() { // act & assert assertThatThrownBy( - () -> sut.updateArticle(member.getId(), study.getId(), 1L, new ArticleRequest("제목 수정", "내용 수정"))) + () -> sut.updateArticle(member.getId(), study.getId(), "community", + 1L, new ArticleRequest("제목 수정", "내용 수정"))) .isInstanceOf(ArticleNotFoundException.class); } @@ -107,12 +104,13 @@ void throwExceptionWhenUpdateByNotParticipant() { .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = communityArticleService.createArticle(member.getId(), study.getId(), + final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), request); // act & assert assertThatThrownBy(() -> sut - .updateArticle(other.getId(), study.getId(), article.getId(), new ArticleRequest("제목 수정", "내용 수정"))) + .updateArticle(other.getId(), study.getId(), "community", + article.getId(), new ArticleRequest("제목 수정", "내용 수정"))) .isInstanceOf(UneditableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingCommunityArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java similarity index 95% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingCommunityArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java index 9b9f80539..e7d85cfd0 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingCommunityArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java @@ -7,7 +7,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.woowacourse.moamoa.WebMVCTest; -import com.woowacourse.moamoa.community.service.CommunityArticleService; +import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import org.junit.jupiter.api.DisplayName; @@ -19,10 +19,10 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -public class CreatingCommunityArticleControllerWebMvcTest extends WebMVCTest { +public class CreatingArticleControllerWebMvcTest extends WebMVCTest { @MockBean - private CommunityArticleService communityArticleService; + private ArticleService articleService; @DisplayName("잘못된 토큰으로 커뮤니티 글을 생성할 경우 401을 반환한다.") @ParameterizedTest @@ -146,7 +146,7 @@ void badRequestByInvalidLengthContent() throws Exception { @DisplayName("스터디에 참여한 참가자가 아닌 경우, NotParticipatedMemberException이 발생하고 401을 반환한다.") @Test void unauthorizedByNotParticipant() throws Exception { - when(communityArticleService.createArticle(any(), any(), any())).thenThrow(NotParticipatedMemberException.class); + when(articleService.createArticle(any(), any(), any())).thenThrow(NotParticipatedMemberException.class); final String token = "Bearer" + tokenProvider.createToken(1L).getAccessToken(); diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingCommunityArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingArticleControllerWebMvcTest.java similarity index 96% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingCommunityArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingArticleControllerWebMvcTest.java index 6104ad81b..b0f7cda04 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingCommunityArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingArticleControllerWebMvcTest.java @@ -12,7 +12,7 @@ import org.junit.jupiter.params.provider.ValueSource; import org.springframework.http.HttpHeaders; -public class DeletingCommunityArticleControllerWebMvcTest extends WebMVCTest { +public class DeletingArticleControllerWebMvcTest extends WebMVCTest { @DisplayName("잘못된 토큰으로 커뮤니티 글을 생성할 경우 401을 반환한다.") @ParameterizedTest diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingCommunityArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingArticleControllerWebMvcTest.java similarity index 98% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingCommunityArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingArticleControllerWebMvcTest.java index 710b1294d..452d4c3df 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingCommunityArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingArticleControllerWebMvcTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.params.provider.ValueSource; import org.springframework.http.HttpHeaders; -public class GettingCommunityArticleControllerWebMvcTest extends WebMVCTest { +public class GettingArticleControllerWebMvcTest extends WebMVCTest { @DisplayName("잘못된 토큰으로 커뮤니티 글을 조회할 경우 401을 반환한다.") @ParameterizedTest diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingCommunityArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingArticleControllerWebMvcTest.java similarity index 98% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingCommunityArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingArticleControllerWebMvcTest.java index 336b9d17a..bedd1d2e3 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingCommunityArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingArticleControllerWebMvcTest.java @@ -15,7 +15,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -public class UpdatingCommunityArticleControllerWebMvcTest extends WebMVCTest { +public class UpdatingArticleControllerWebMvcTest extends WebMVCTest { @DisplayName("잘못된 토큰으로 커뮤니티 글을 수정할 경우 401을 반환한다.") @ParameterizedTest From fe1ad0368fba35e9e9de3cd67829d160dff66da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=98=81?= Date: Fri, 12 Aug 2022 21:17:55 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?= =?UTF-8?q?=EA=B3=B5=EC=A7=80=EC=82=AC=ED=95=AD=20CRUD=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/config/AuthRequestMatchConfig.java | 29 +-- .../controller/ArticleController.java | 14 +- .../moamoa/community/domain/Article.java | 110 ++++++++- .../community/domain/CommunityArticle.java | 72 +----- .../community/domain/NoticeArticle.java | 52 +++++ .../domain/repository/ArticleRepository.java | 13 ++ .../CommunityArticleRepository.java | 35 ++- .../JpaCommunityArticleRepository.java | 7 + .../JpaNoticeArticleRepository.java | 7 + .../repository/NoticeArticleRepository.java | 39 ++++ .../moamoa/community/query/ArticleDao.java | 83 +++++++ .../community/query/CommunityArticleDao.java | 80 ------- ...unityArticleData.java => ArticleData.java} | 8 +- .../service/ArticleRepositoryFactory.java | 32 +++ .../community/service/ArticleService.java | 50 ++-- .../service/response/ArticleResponse.java | 4 +- .../response/ArticleSummaryResponse.java | 4 +- .../acceptance/AcceptanceTest.java | 3 +- .../acceptance/steps/StudyRelatedSteps.java | 24 +- .../test/notice/NoticeAcceptanceTest.java | 213 +++++++++++++++++- .../controller/ArticleControllerTest.java | 36 ++- .../DeletingArticleControllerTest.java | 22 +- .../GettingArticleControllerTest.java | 22 +- ...mmunityArticleSummariesControllerTest.java | 30 ++- .../UpdatingArticleControllerTest.java | 23 +- .../domain/CommunityArticleTest.java | 14 +- .../CreatingArticleControllerWebMvcTest.java | 2 +- backend/src/test/resources/schema.sql | 18 +- 28 files changed, 786 insertions(+), 260 deletions(-) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/query/CommunityArticleDao.java rename backend/src/main/java/com/woowacourse/moamoa/community/query/data/{CommunityArticleData.java => ArticleData.java} (68%) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java diff --git a/backend/src/main/java/com/woowacourse/moamoa/auth/config/AuthRequestMatchConfig.java b/backend/src/main/java/com/woowacourse/moamoa/auth/config/AuthRequestMatchConfig.java index 5d037fc64..630507ebb 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/auth/config/AuthRequestMatchConfig.java +++ b/backend/src/main/java/com/woowacourse/moamoa/auth/config/AuthRequestMatchConfig.java @@ -1,5 +1,7 @@ package com.woowacourse.moamoa.auth.config; +import static org.springframework.http.HttpMethod.*; + import com.woowacourse.moamoa.auth.controller.matcher.AuthenticationRequestMatcher; import com.woowacourse.moamoa.auth.controller.matcher.AuthenticationRequestMatcherBuilder; import lombok.AllArgsConstructor; @@ -14,30 +16,23 @@ public class AuthRequestMatchConfig { @Bean public AuthenticationRequestMatcher authenticationRequestMatcher() { return new AuthenticationRequestMatcherBuilder() - .addUpAuthenticationPath(HttpMethod.POST, + .addUpAuthenticationPath(POST, "/api/studies", "/api/studies/\\d+/reviews", "/api/studies/\\d+/reviews/\\d+", - "/api/studies/\\w+/community/articles", - "/api/studies" - ) - .addUpAuthenticationPath(HttpMethod.GET, + "/api/studies/\\w+/\\w+/articles", + "/api/studies") + .addUpAuthenticationPath(GET, "/api/my/studies", "/api/members/me", "/api/members/me/role", - "/api/studies/\\w+/community/articles/\\w+", - "/api/studies/\\w+/community/articles", - "/api/studies/\\d+/reference-room/links" - ) - .addUpAuthenticationPath(HttpMethod.PUT, - "/api/studies/\\d+/reviews/\\d+", - "/api/studies/\\d+/reference-room/links/\\d+" - ) - .addUpAuthenticationPath(HttpMethod.DELETE, + "/api/studies/\\w+/\\w+/articles/\\w+", + "/api/studies/\\w+/\\w+/articles") + .addUpAuthenticationPath(PUT, + "/api/studies/\\d+/reviews/\\d+") + .addUpAuthenticationPath(DELETE, "/api/studies/\\d+/reviews/\\d+", - "/api/studies/\\w+/community/articles/\\w+", - "/api/studies/\\d+/reference-room/links/\\d+" - ) + "/api/studies/\\w+/\\w+/articles/\\w+") .build(); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java b/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java index c8ca5d8ae..91a2eefa5 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java @@ -1,7 +1,7 @@ package com.woowacourse.moamoa.community.controller; import com.woowacourse.moamoa.auth.config.AuthenticatedMember; -import com.woowacourse.moamoa.community.domain.CommunityArticle; +import com.woowacourse.moamoa.community.domain.Article; import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.community.service.response.ArticleResponse; @@ -36,8 +36,8 @@ public ResponseEntity createArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, @PathVariable("article-type") final String articleType, @Valid @RequestBody final ArticleRequest request) { - final CommunityArticle article = articleService.createArticle(id, studyId, request); - final URI location = URI.create("/api/studies/" + studyId + "/community/articles/" + article.getId()); + final Article article = articleService.createArticle(id, studyId, request, articleType); + final URI location = URI.create("/api/studies/" + studyId + "/" + articleType + "/articles/" + article.getId()); return ResponseEntity.created(location).header("Access-Control-Allow-Headers", HttpHeaders.LOCATION).build(); } @@ -47,7 +47,7 @@ public ResponseEntity getArticle(@AuthenticatedMember final Lon @PathVariable("article-type") final String articleType, @PathVariable("article-id") final Long articleId ) { - ArticleResponse response = articleService.getArticle(id, studyId, articleId); + ArticleResponse response = articleService.getArticle(id, studyId, articleId, articleType); return ResponseEntity.ok().body(response); } @@ -57,7 +57,7 @@ public ResponseEntity deleteArticle(@AuthenticatedMember final Long id, @PathVariable("article-type") final String articleType, @PathVariable("article-id") final Long articleId ) { - articleService.deleteArticle(id, studyId, articleId); + articleService.deleteArticle(id, studyId, articleId, articleType); return ResponseEntity.noContent().build(); } @@ -67,7 +67,7 @@ public ResponseEntity getArticles(@AuthenticatedMember @PathVariable("article-type") final String articleType, @PageableDefault final Pageable pageable ) { - ArticleSummariesResponse response = articleService.getArticles(id, studyId, pageable); + ArticleSummariesResponse response = articleService.getArticles(id, studyId, pageable, articleType); return ResponseEntity.ok().body(response); } @@ -78,7 +78,7 @@ public ResponseEntity updateArticle(@AuthenticatedMember final Long id, @PathVariable("article-id") final Long articleId, @Valid @RequestBody final ArticleRequest request ) { - articleService.updateArticle(id, studyId, articleId, request); + articleService.updateArticle(id, studyId, articleId, request, articleType); return ResponseEntity.noContent().build(); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java index 9ac3673d8..ba09ecddc 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java @@ -1,10 +1,112 @@ package com.woowacourse.moamoa.community.domain; -public interface Article { +import static javax.persistence.GenerationType.IDENTITY; - void update(final String title, final String content); +import com.woowacourse.moamoa.common.entity.BaseEntity; +import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.member.domain.Member; +import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; +import com.woowacourse.moamoa.study.domain.MemberRole; +import com.woowacourse.moamoa.study.domain.Study; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; +import lombok.Getter; +import lombok.NoArgsConstructor; - boolean isViewableBy(final Long studyId, final Long memberId); +@MappedSuperclass +@NoArgsConstructor +@Getter +public abstract class Article extends BaseEntity { - boolean isEditableBy(final Long studyId, final Long memberId); + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + private String title; + + private String content; + + @Column(name = "author_id") + private Long authorId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "study_id") + private Study study; + + Article(final String title, final String content, final Long authorId, final Study study) { + this(null, title, content, authorId, study); + } + + public Article(final Long id, final String title, final String content, final Long authorId, + final Study study) { + this.id = id; + this.title = title; + this.content = content; + this.authorId = authorId; + this.study = study; + } + + public void update(final String title, final String content) { + this.title = title; + this.content = content; + } + + public boolean isViewableBy(final Long studyId, final Long memberId) { + return isBelongTo(studyId) && study.isParticipant(memberId); + } + + public boolean isEditableBy(final Long studyId, final Long memberId) { + return isViewableBy(studyId, memberId) && isAuthor(memberId); + } + + private boolean isBelongTo(final Long studyId) { + return this.study.getId().equals(studyId); + } + + private boolean isAuthor(final Long memberId) { + return this.authorId.equals(memberId); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final CommunityArticle that = (CommunityArticle) o; + return Objects.equals(getId(), that.getId()) && Objects.equals(getTitle(), that.getTitle()) + && Objects.equals(getContent(), that.getContent()) && Objects.equals(getAuthorId(), + that.getAuthorId()) && Objects.equals(getStudy().getId(), that.getStudy().getId()); + } + + @Override + public int hashCode() { + return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudy().getId()); + } + + public static Article write(final Member member, final Study study, final ArticleRequest request, + final String articleType) { + final MemberRole role = study.getRole(member.getId()); + + if (articleType.equals("community")) { + if (role.equals(MemberRole.NON_MEMBER)) { + throw new NotParticipatedMemberException(); + } + return new CommunityArticle(request.getTitle(), request.getContent(), member.getId(), study); + } + + if (role.equals(MemberRole.OWNER)) { + return new NoticeArticle(request.getTitle(), request.getContent(), member.getId(), study); + } + + throw new NotParticipatedMemberException(); + } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java index 4adb36eb4..ae15c7f22 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java @@ -1,86 +1,24 @@ package com.woowacourse.moamoa.community.domain; -import static javax.persistence.GenerationType.IDENTITY; - -import com.woowacourse.moamoa.common.entity.BaseEntity; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.member.domain.Member; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.Study; import java.util.Objects; -import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; import javax.persistence.Table; import lombok.AccessLevel; -import lombok.Getter; import lombok.NoArgsConstructor; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Table(name = "article") -public class CommunityArticle extends BaseEntity { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Long id; - - private String title; - - private String content; - - @Column(name = "author_id") - private Long authorId; +@Table(name = "community") +public class CommunityArticle extends Article { - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "study_id") - private Study study; - - private CommunityArticle(final String title, final String content, final Long authorId, final Study study) { - this(null, title, content, authorId, study); + CommunityArticle(final String title, final String content, final Long authorId, final Study study) { + super(null, title, content, authorId, study); } public CommunityArticle(final Long id, final String title, final String content, final Long authorId, final Study study) { - this.id = id; - this.title = title; - this.content = content; - this.authorId = authorId; - this.study = study; - } - - public static CommunityArticle write(final Member member, final Study study, final ArticleRequest request) { - if (!study.isParticipant(member.getId())) { - throw new NotParticipatedMemberException(); - } - - return new CommunityArticle(request.getTitle(), request.getContent(), member.getId(), study); - } - - public void update(final String title, final String content) { - this.title = title; - this.content = content; - } - - public boolean isViewableBy(final Long studyId, final Long memberId) { - return isBelongTo(studyId) && study.isParticipant(memberId); - } - - public boolean isEditableBy(final Long studyId, final Long memberId) { - return isViewableBy(studyId, memberId) && isAuthor(memberId); - } - - private boolean isBelongTo(final Long studyId) { - return this.study.getId().equals(studyId); - } - - private boolean isAuthor(final Long memberId) { - return this.authorId.equals(memberId); + super(id, title, content, authorId, study); } @Override diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java new file mode 100644 index 000000000..4d26219ff --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java @@ -0,0 +1,52 @@ +package com.woowacourse.moamoa.community.domain; + +import static javax.persistence.GenerationType.IDENTITY; + +import com.woowacourse.moamoa.common.entity.BaseEntity; +import com.woowacourse.moamoa.study.domain.Study; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "notice") +public class NoticeArticle extends Article { + + NoticeArticle(final String title, final String content, final Long authorId, final Study study) { + super(null, title, content, authorId, study); + } + + public NoticeArticle(final Long id, final String title, final String content, final Long authorId, + final Study study) { + super(id, title, content, authorId, study); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final NoticeArticle that = (NoticeArticle) o; + return Objects.equals(getId(), that.getId()) && Objects.equals(getTitle(), that.getTitle()) + && Objects.equals(getContent(), that.getContent()) && Objects.equals(getAuthorId(), + that.getAuthorId()) && Objects.equals(getStudy().getId(), that.getStudy().getId()); + } + + @Override + public int hashCode() { + return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudy().getId()); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java new file mode 100644 index 000000000..831d9af71 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java @@ -0,0 +1,13 @@ +package com.woowacourse.moamoa.community.domain.repository; + +import com.woowacourse.moamoa.community.domain.Article; +import java.util.Optional; + +public interface ArticleRepository { + + Article save(Article article); + + Optional
findById(Long id); + + void deleteById(Long id); +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java index d7b1d0dd5..fd4a0258c 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java @@ -1,7 +1,38 @@ package com.woowacourse.moamoa.community.domain.repository; +import com.woowacourse.moamoa.community.domain.Article; import com.woowacourse.moamoa.community.domain.CommunityArticle; -import org.springframework.data.jpa.repository.JpaRepository; +import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; +import java.util.Optional; +import org.springframework.stereotype.Repository; -public interface CommunityArticleRepository extends JpaRepository { +@Repository +public class CommunityArticleRepository implements ArticleRepository { + + private final JpaCommunityArticleRepository jpaCommunityArticleRepository; + + public CommunityArticleRepository( + final JpaCommunityArticleRepository jpaCommunityArticleRepository) { + this.jpaCommunityArticleRepository = jpaCommunityArticleRepository; + } + + @Override + public Article save(Article article) { + return jpaCommunityArticleRepository.save((CommunityArticle) article); + } + + @Override + public Optional
findById(Long id) { + final CommunityArticle article = jpaCommunityArticleRepository.findById(id).orElseThrow( + () -> new ArticleNotFoundException(id)); + return Optional.of(article); + } + + public void deleteById(final Long articleId) { + jpaCommunityArticleRepository.deleteById(articleId); + } + + public boolean existsById(final Long id) { + return jpaCommunityArticleRepository.existsById(id); + } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java new file mode 100644 index 000000000..f1083b2f2 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java @@ -0,0 +1,7 @@ +package com.woowacourse.moamoa.community.domain.repository; + +import com.woowacourse.moamoa.community.domain.CommunityArticle; +import org.springframework.data.jpa.repository.JpaRepository; + +interface JpaCommunityArticleRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java new file mode 100644 index 000000000..834bfc198 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java @@ -0,0 +1,7 @@ +package com.woowacourse.moamoa.community.domain.repository; + +import com.woowacourse.moamoa.community.domain.NoticeArticle; +import org.springframework.data.jpa.repository.JpaRepository; + +interface JpaNoticeArticleRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java new file mode 100644 index 000000000..cd433bfd5 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java @@ -0,0 +1,39 @@ +package com.woowacourse.moamoa.community.domain.repository; + +import com.woowacourse.moamoa.community.domain.Article; +import com.woowacourse.moamoa.community.domain.CommunityArticle; +import com.woowacourse.moamoa.community.domain.NoticeArticle; +import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; +import java.util.Optional; +import org.springframework.stereotype.Repository; + +@Repository +public class NoticeArticleRepository implements ArticleRepository { + + private final JpaNoticeArticleRepository noticeArticleRepository; + + public NoticeArticleRepository( + final JpaNoticeArticleRepository noticeArticleRepository) { + this.noticeArticleRepository = noticeArticleRepository; + } + + @Override + public Article save(Article article) { + return noticeArticleRepository.save((NoticeArticle) article); + } + + @Override + public Optional
findById(Long id) { + final NoticeArticle article = noticeArticleRepository.findById(id).orElseThrow( + () -> new ArticleNotFoundException(id)); + return Optional.of(article); + } + + public void deleteById(final Long articleId) { + noticeArticleRepository.deleteById(articleId); + } + + public boolean existsById(final Long id) { + return noticeArticleRepository.existsById(id); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java b/backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java new file mode 100644 index 000000000..db9c2b171 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java @@ -0,0 +1,83 @@ +package com.woowacourse.moamoa.community.query; + +import com.woowacourse.moamoa.community.query.data.ArticleData; +import com.woowacourse.moamoa.member.query.data.MemberData; +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +@Repository +public class ArticleDao { + + public static final RowMapper ROW_MAPPER = (rs, rn) -> { + final long id = rs.getLong("article_id"); + final String title = rs.getString("article_title"); + final String content = rs.getString("article_content"); + final LocalDate createdDate = rs.getObject("article_created_date", LocalDate.class); + final LocalDate lastModifiedDate = rs.getObject("article_last_modified_date", LocalDate.class); + + final long githubId = rs.getLong("member.github_id"); + final String username = rs.getString("member.username"); + final String imageUrl = rs.getString("member.image_url"); + final String profileUrl = rs.getString("member.profile_url"); + MemberData memberData = new MemberData(githubId, username, imageUrl, profileUrl); + + return new ArticleData(id, memberData, title, content, createdDate, lastModifiedDate); + }; + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + + + public ArticleDao(final NamedParameterJdbcTemplate namedParameterJdbcTemplate) { + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; + } + + public Optional getById(final Long communityId, final String articleType) { + final String sql = "SELECT {}.id as article_id, {}.title as article_title, {}.content as article_content, " + + "{}.created_date as article_created_date, {}.last_modified_date as article_last_modified_date, " + + "member.github_id, member.username, member.image_url, member.profile_url " + + "FROM {} JOIN member ON {}.author_id = member.id " + + "WHERE {}.id = :{}Id"; + + final Map params = Map.of(articleType + "Id", communityId); + return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", articleType), params, ROW_MAPPER).stream().findAny(); + } + + public Page getAllByStudyId(final Long studyId, final Pageable pageable, + final String articleType) { + final List content = getContent(studyId, pageable, articleType); + final int totalCount = getTotalCount(studyId, articleType); + return new PageImpl<>(content, pageable, totalCount); + } + + private List getContent(final Long studyId, final Pageable pageable, + final String articleType) { + final String sql = "SELECT {}.id as article_id, {}.title as article_title, {}.content as article_content, " + + "{}.created_date as article_created_date, {}.last_modified_date as article_last_modified_date, " + + "member.github_id, member.username, member.image_url, member.profile_url " + + "FROM {} JOIN member ON {}.author_id = member.id " + + "WHERE {}.study_id = :studyId " + + "ORDER BY created_date DESC, {}.id DESC " + + "LIMIT :size OFFSET :offset"; + + final Map params = Map.of( + "studyId", studyId, + "size", pageable.getPageSize(), + "offset", pageable.getOffset() + ); + + return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", articleType), params, ROW_MAPPER); + } + + private int getTotalCount(final Long studyId, final String articleType) { + final String sql = "SELECT count({}.id) FROM {} WHERE {}.study_id = :studyId"; + final Map param = Map.of("studyId", studyId); + return namedParameterJdbcTemplate.queryForObject(sql.replaceAll("\\{\\}", articleType), param, (rs, rn) -> rs.getInt(1)); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/query/CommunityArticleDao.java b/backend/src/main/java/com/woowacourse/moamoa/community/query/CommunityArticleDao.java deleted file mode 100644 index c8b5c4e49..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/query/CommunityArticleDao.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.woowacourse.moamoa.community.query; - -import com.woowacourse.moamoa.community.query.data.CommunityArticleData; -import com.woowacourse.moamoa.member.query.data.MemberData; -import java.time.LocalDate; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Repository; - -@Repository -public class CommunityArticleDao { - - public static final RowMapper ROW_MAPPER = (rs, rn) -> { - final long id = rs.getLong("article.id"); - final String title = rs.getString("article.title"); - final String content = rs.getString("article.content"); - final LocalDate createdDate = rs.getObject("article.created_date", LocalDate.class); - final LocalDate lastModifiedDate = rs.getObject("article.last_modified_date", LocalDate.class); - - final long githubId = rs.getLong("member.github_id"); - final String username = rs.getString("member.username"); - final String imageUrl = rs.getString("member.image_url"); - final String profileUrl = rs.getString("member.profile_url"); - MemberData memberData = new MemberData(githubId, username, imageUrl, profileUrl); - - return new CommunityArticleData(id, memberData, title, content, createdDate, lastModifiedDate); - }; - private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; - - - public CommunityArticleDao(final NamedParameterJdbcTemplate namedParameterJdbcTemplate) { - this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; - } - - public Optional getById(final Long articleId) { - final String sql = "SELECT article.id, article.title, article.content, " - + "article.created_date, article.last_modified_date, " - + "member.github_id, member.username, member.image_url, member.profile_url " - + "FROM article JOIN member ON article.author_id = member.id " - + "WHERE article.id = :articleId"; - final Map params = Map.of("articleId", articleId); - return namedParameterJdbcTemplate.query(sql, params, ROW_MAPPER).stream().findAny(); - } - - public Page getAllByStudyId(final Long studyId, final Pageable pageable) { - final List content = getContent(studyId, pageable); - final int totalCount = getTotalCount(studyId); - return new PageImpl<>(content, pageable, totalCount); - } - - private List getContent(final Long studyId, final Pageable pageable) { - final String sql = "SELECT article.id, article.title, article.content, " - + "article.created_date, article.last_modified_date, " - + "member.github_id, member.username, member.image_url, member.profile_url " - + "FROM article JOIN member ON article.author_id = member.id " - + "WHERE article.study_id = :studyId " - + "ORDER BY created_date DESC, id DESC " - + "LIMIT :size OFFSET :offset"; - - final Map params = Map.of( - "studyId", studyId, - "size", pageable.getPageSize(), - "offset", pageable.getOffset() - ); - - return namedParameterJdbcTemplate.query(sql, params, ROW_MAPPER); - } - - private int getTotalCount(final Long studyId) { - final String sql = "SELECT count(article.id) FROM article WHERE article.study_id = :studyId"; - final Map param = Map.of("studyId", studyId); - return namedParameterJdbcTemplate.queryForObject(sql, param, (rs, rn) -> rs.getInt(1)); - } -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/query/data/CommunityArticleData.java b/backend/src/main/java/com/woowacourse/moamoa/community/query/data/ArticleData.java similarity index 68% rename from backend/src/main/java/com/woowacourse/moamoa/community/query/data/CommunityArticleData.java rename to backend/src/main/java/com/woowacourse/moamoa/community/query/data/ArticleData.java index 8814fb211..21929e2b4 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/query/data/CommunityArticleData.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/query/data/ArticleData.java @@ -5,7 +5,7 @@ import lombok.Getter; @Getter -public class CommunityArticleData { +public class ArticleData { private final Long id; private final MemberData memberData; @@ -14,9 +14,9 @@ public class CommunityArticleData { private final LocalDate createdDate; private final LocalDate lastModifiedDate; - public CommunityArticleData(final Long id, final MemberData memberData, final String title, final String content, - final LocalDate createdDate, - final LocalDate lastModifiedDate) { + public ArticleData(final Long id, final MemberData memberData, final String title, final String content, + final LocalDate createdDate, + final LocalDate lastModifiedDate) { this.id = id; this.memberData = memberData; this.title = title; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java new file mode 100644 index 000000000..62ab35c48 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java @@ -0,0 +1,32 @@ +package com.woowacourse.moamoa.community.service; + +import com.woowacourse.moamoa.community.domain.repository.ArticleRepository; +import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; +import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; +import com.woowacourse.moamoa.member.domain.repository.MemberRepository; +import org.springframework.stereotype.Component; + +@Component +public class ArticleRepositoryFactory { + + private final CommunityArticleRepository communityArticleRepository; + private final NoticeArticleRepository noticeArticleRepository; + + public ArticleRepositoryFactory( + final CommunityArticleRepository communityArticleRepository, + final NoticeArticleRepository noticeArticleRepository) { + this.communityArticleRepository = communityArticleRepository; + this.noticeArticleRepository = noticeArticleRepository; + } + + public ArticleRepository getRepository() { + return communityArticleRepository; + } + + public ArticleRepository getRepository(final String articleType) { + if (articleType.equals("community")) { + return communityArticleRepository; + } + return noticeArticleRepository; + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java index 31ca6f5f9..349111fbc 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java @@ -1,9 +1,8 @@ package com.woowacourse.moamoa.community.service; -import com.woowacourse.moamoa.community.domain.CommunityArticle; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.query.CommunityArticleDao; -import com.woowacourse.moamoa.community.query.data.CommunityArticleData; +import com.woowacourse.moamoa.community.domain.Article; +import com.woowacourse.moamoa.community.query.ArticleDao; +import com.woowacourse.moamoa.community.query.data.ArticleData; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; @@ -19,6 +18,7 @@ import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import java.util.List; import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -30,61 +30,65 @@ public class ArticleService { private final MemberRepository memberRepository; private final StudyRepository studyRepository; - private final CommunityArticleRepository communityArticleRepository; - private final CommunityArticleDao communityArticleDao; + private final ArticleDao articleDao; + private final ArticleRepositoryFactory factory; + @Autowired public ArticleService(final MemberRepository memberRepository, final StudyRepository studyRepository, - final CommunityArticleRepository communityArticleRepository, - final CommunityArticleDao communityArticleDao) { + final ArticleDao articleDao, + ArticleRepositoryFactory factory) { this.memberRepository = memberRepository; this.studyRepository = studyRepository; - this.communityArticleRepository = communityArticleRepository; - this.communityArticleDao = communityArticleDao; + this.articleDao = articleDao; + this.factory = factory; } @Transactional - public CommunityArticle createArticle(final Long memberId, final Long studyId, - final ArticleRequest request) { + public Article createArticle(final Long memberId, final Long studyId, + final ArticleRequest request, final String articleType) { final Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); final Study study = studyRepository.findById(studyId).orElseThrow(StudyNotFoundException::new); - return communityArticleRepository.save(CommunityArticle.write(member, study, request)); + return factory.getRepository(articleType).save(Article.write(member, study, request, articleType)); } - public ArticleResponse getArticle(final Long memberId, final Long studyId, final Long articleId) { - final CommunityArticle article = communityArticleRepository.findById(articleId) + public ArticleResponse getArticle(final Long memberId, final Long studyId, final Long articleId, + final String articleType) { + final Article article = factory.getRepository(articleType).findById(articleId) .orElseThrow(() -> new ArticleNotFoundException(articleId)); if (!article.isViewableBy(studyId, memberId)) { throw new UnviewableArticleException(studyId, memberId); } - final CommunityArticleData data = communityArticleDao.getById(articleId) + final ArticleData data = articleDao.getById(articleId, articleType) .orElseThrow(() -> new ArticleNotFoundException(articleId)); return new ArticleResponse(data); } @Transactional - public void deleteArticle(final Long memberId, final Long studyId, final Long articleId) { - final CommunityArticle article = communityArticleRepository.findById(articleId) + public void deleteArticle(final Long memberId, final Long studyId, final Long articleId, + final String articleType) { + final Article article = factory.getRepository(articleType).findById(articleId) .orElseThrow(() -> new ArticleNotFoundException(articleId)); if (!article.isEditableBy(studyId, memberId)) { throw new UneditableArticleException(); } - communityArticleRepository.deleteById(articleId); + factory.getRepository(articleType).deleteById(articleId); } - public ArticleSummariesResponse getArticles(final Long memberId, final Long studyId, final Pageable pageable) { + public ArticleSummariesResponse getArticles(final Long memberId, final Long studyId, final Pageable pageable, + String articleType) { final Study study = studyRepository.findById(studyId).orElseThrow(StudyNotFoundException::new); if (!study.isParticipant(memberId)) { throw new UnviewableArticleException(studyId, memberId); } - final Page page = communityArticleDao.getAllByStudyId(studyId, pageable); + final Page page = articleDao.getAllByStudyId(studyId, pageable, articleType); final List articles = page.getContent().stream() .map(ArticleSummaryResponse::new) @@ -95,8 +99,8 @@ public ArticleSummariesResponse getArticles(final Long memberId, final Long stud @Transactional public void updateArticle(final Long memberId, final Long studyId, final Long articleId, - final ArticleRequest request) { - final CommunityArticle article = communityArticleRepository.findById(articleId) + final ArticleRequest request, final String articleType) { + final Article article = factory.getRepository(articleType).findById(articleId) .orElseThrow(() -> new ArticleNotFoundException(articleId)); if (!article.isEditableBy(studyId, memberId)) { diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java b/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java index 409c7f593..8f23b7e94 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java @@ -1,6 +1,6 @@ package com.woowacourse.moamoa.community.service.response; -import com.woowacourse.moamoa.community.query.data.CommunityArticleData; +import com.woowacourse.moamoa.community.query.data.ArticleData; import java.time.LocalDate; import lombok.AllArgsConstructor; import lombok.Builder; @@ -24,7 +24,7 @@ public class ArticleResponse { private LocalDate createdDate; private LocalDate lastModifiedDate; - public ArticleResponse(CommunityArticleData data) { + public ArticleResponse(ArticleData data) { this(data.getId(), new AuthorResponse(data.getMemberData()), data.getTitle(), data.getContent(), data.getCreatedDate(), data.getLastModifiedDate()); } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java b/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java index 1f5bc7543..f2b252387 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java +++ b/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java @@ -1,6 +1,6 @@ package com.woowacourse.moamoa.community.service.response; -import com.woowacourse.moamoa.community.query.data.CommunityArticleData; +import com.woowacourse.moamoa.community.query.data.ArticleData; import java.time.LocalDate; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -19,7 +19,7 @@ public class ArticleSummaryResponse { private LocalDate createdDate; private LocalDate lastModifiedDate; - public ArticleSummaryResponse(CommunityArticleData data) { + public ArticleSummaryResponse(ArticleData data) { this.id = data.getId(); this.author = new AuthorResponse(data.getMemberData()); this.title = data.getTitle(); diff --git a/backend/src/test/java/com/woowacourse/acceptance/AcceptanceTest.java b/backend/src/test/java/com/woowacourse/acceptance/AcceptanceTest.java index 5bce1bd77..e9800e538 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/woowacourse/acceptance/AcceptanceTest.java @@ -96,7 +96,8 @@ void mockingGithubServer() { @AfterEach void tearDown() { jdbcTemplate.update("SET REFERENTIAL_INTEGRITY FALSE"); - jdbcTemplate.update("TRUNCATE TABLE article"); + jdbcTemplate.update("TRUNCATE TABLE notice"); + jdbcTemplate.update("TRUNCATE TABLE community"); jdbcTemplate.update("TRUNCATE TABLE member"); jdbcTemplate.update("TRUNCATE TABLE study_tag"); jdbcTemplate.update("TRUNCATE TABLE study_member"); diff --git a/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java b/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java index d8aced7dc..6fd0e95f9 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java +++ b/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java @@ -50,7 +50,6 @@ public class StudyRelatedSteps extends Steps { return null; } } - public Long 링크를_공유한다(final CreatingLinkRequest request) { try { final String location = RestAssured.given().log().all() @@ -69,7 +68,26 @@ public class StudyRelatedSteps extends Steps { } } - public Long 게시글을_작성한다(final String title, final String content) { + public long 공지사항을_작성한다(final String title, final String content) { + try { + final String location = RestAssured.given().log().all() + .header(org.apache.http.HttpHeaders.AUTHORIZATION, token) + .header(org.apache.http.HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .body(objectMapper.writeValueAsString(new ArticleRequest(title, content))) + .pathParam("study-id", studyId) + .when().log().all() + .post("/api/studies/{study-id}/notice/articles") + .then().log().all() + .statusCode(HttpStatus.CREATED.value()) + .extract().header(HttpHeaders.LOCATION); + return Long.parseLong(location.replaceAll("/api/studies/" + studyId + "/notice/articles/", "")); + } catch (Exception e) { + Assertions.fail("공지사항 작성 실패"); + return -1; + } + } + + public long 게시글을_작성한다(final String title, final String content) { try { final String location = RestAssured.given().log().all() .header(org.apache.http.HttpHeaders.AUTHORIZATION, token) @@ -84,7 +102,7 @@ public class StudyRelatedSteps extends Steps { return Long.parseLong(location.replaceAll("/api/studies/" + studyId + "/community/articles/", "")); } catch (Exception e) { Assertions.fail("게시글 작성 실패"); - return null; + return -1; } } } diff --git a/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java b/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java index 5b3a8c693..4fac2470f 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java +++ b/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java @@ -4,7 +4,12 @@ import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이름; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이미지_URL; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_프로필_URL; +import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_깃허브_ID; +import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_이름; +import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_이미지_URL; +import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_프로필_URL; import static com.woowacourse.acceptance.steps.LoginSteps.그린론이; +import static com.woowacourse.acceptance.steps.LoginSteps.베루스가; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; @@ -14,15 +19,21 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document; +import com.fasterxml.jackson.core.JsonProcessingException; import com.woowacourse.acceptance.AcceptanceTest; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.community.service.response.ArticleResponse; +import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; +import com.woowacourse.moamoa.community.service.response.ArticleSummaryResponse; import com.woowacourse.moamoa.community.service.response.AuthorResponse; import io.restassured.RestAssured; import java.time.LocalDate; +import java.util.List; import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; @@ -37,7 +48,7 @@ void writeNotice() throws Exception { // arrange long 스터디_ID = 그린론이().로그인하고().자바_스터디를().시작일자는(LocalDate.now()).생성한다(); String 토큰 = 그린론이().로그인한다(); - ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); + ArticleRequest request = new ArticleRequest("공지사항 제목", "공지사항 내용"); // act final String location = RestAssured.given(spec).log().all() @@ -118,4 +129,204 @@ void writeNotice() throws Exception { assertThat(actualResponse).isEqualTo(expectedResponse); } + + @DisplayName("스터디 공지사항 게시글을 삭제한다.") + @Test + void deleteCommunityArticle() { + // arrange + long 스터디_ID = 그린론이().로그인하고().자바_스터디를().시작일자는(LocalDate.now()).생성한다(); + long 공지사항_ID = 그린론이().로그인하고().스터디에(스터디_ID).공지사항을_작성한다("게시글 제목", "게시글 내용"); + String 토큰 = 그린론이().로그인한다(); + + // act + RestAssured.given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .pathParam("study-id", 스터디_ID) + .pathParam("article-id", 공지사항_ID) + .filter(document("delete/notice", + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("JWT 토큰") + ), + pathParameters( + parameterWithName("study-id").description("스터디 식별 번호"), + parameterWithName("article-id").description("게시글 식별 번호") + ) + )) + .when().log().all() + .delete("/api/studies/{study-id}/notice/articles/{article-id}") + .then().log().all() + .statusCode(HttpStatus.NO_CONTENT.value()); + + // assert + RestAssured + .given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .pathParam("study-id", 스터디_ID) + .pathParam("article-id", 공지사항_ID) + .when().log().all() + .get("/api/studies/{study-id}/notice/articles/{article-id}") + .then().log().all() + .statusCode(HttpStatus.NOT_FOUND.value()); + } + + @DisplayName("스터디 공지사항 전체 게시글을 조회한다.") + @Test + void getStudyCommunityArticles() { + // arrange + long 자바_스터디_ID = 그린론이().로그인하고().자바_스터디를().시작일자는(LocalDate.now()).생성한다(); + 그린론이().로그인하고().스터디에(자바_스터디_ID).공지사항을_작성한다("자바 게시글 제목1", "자바 게시글 내용1"); + long 자바_공지글2_ID = 그린론이().로그인하고().스터디에(자바_스터디_ID).공지사항을_작성한다("자바 게시글 제목2", "자바 게시글 내용2"); + long 자바_공지글3_ID = 그린론이().로그인하고().스터디에(자바_스터디_ID).공지사항을_작성한다("자바 게시글 제목3", "자바 게시글 내용3"); + long 자바_공지글4_ID = 그린론이().로그인하고().스터디에(자바_스터디_ID).공지사항을_작성한다("자바 게시글 제목4", "자바 게시글 내용4"); + + long 리액트_스터디_ID = 베루스가().로그인하고().리액트_스터디를().시작일자는(LocalDate.now()).생성한다(); + 베루스가().로그인하고().스터디에(리액트_스터디_ID).공지사항을_작성한다("리액트 게시글 제목", "리액트 게시글 내용"); + + String 토큰 = 그린론이().로그인한다(); + + // act + final ArticleSummariesResponse response = RestAssured.given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .pathParam("study-id", 자바_스터디_ID) + .queryParam("page", 0) + .queryParam("size", 3) + .filter(document("get/notices", + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Jwt 토큰") + ), + pathParameters( + parameterWithName("study-id").description("스터디 ID") + ), + requestParameters( + parameterWithName("page").description("페이지"), + parameterWithName("size").description("사이즈") + ), + responseFields( + fieldWithPath("articles").type(JsonFieldType.ARRAY).description("게시물 목록"), + fieldWithPath("articles[].id").type(JsonFieldType.NUMBER).description("게시글 식별 ID"), + fieldWithPath("articles[].author").type(JsonFieldType.OBJECT).description("작성자"), + fieldWithPath("articles[].author.id").type(JsonFieldType.NUMBER) + .description("작성자 github ID"), + fieldWithPath("articles[].author.username").type(JsonFieldType.STRING) + .description("작성자 github 사용자 이름"), + fieldWithPath("articles[].author.imageUrl").type(JsonFieldType.STRING) + .description("작성자 github 이미지 URL"), + fieldWithPath("articles[].author.profileUrl").type(JsonFieldType.STRING) + .description("작성자 github 프로필 URL"), + fieldWithPath("articles[].title").type(JsonFieldType.STRING).description("게시글 제목"), + fieldWithPath("articles[].createdDate").type(JsonFieldType.STRING) + .description("게시글 작성일"), + fieldWithPath("articles[].lastModifiedDate").type(JsonFieldType.STRING) + .description("게시글 수정일"), + fieldWithPath("currentPage").type(JsonFieldType.NUMBER).description("현재 페이지 번호"), + fieldWithPath("lastPage").type(JsonFieldType.NUMBER).description("마지막 페이지 번호"), + fieldWithPath("totalCount").type(JsonFieldType.NUMBER).description("게시글 전체 갯수") + ) + )) + .when().log().all() + .get("/api/studies/{study-id}/notice/articles") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract().as(ArticleSummariesResponse.class); + + // assert + AuthorResponse 그린론 = new AuthorResponse(그린론_깃허브_ID, 그린론_이름, 그린론_이미지_URL, 그린론_프로필_URL); + + List articles = List.of( + new ArticleSummaryResponse(자바_공지글4_ID, 그린론, "자바 게시글 제목4", LocalDate.now(), LocalDate.now()), + new ArticleSummaryResponse(자바_공지글3_ID, 그린론, "자바 게시글 제목3", LocalDate.now(), LocalDate.now()), + new ArticleSummaryResponse(자바_공지글2_ID, 그린론, "자바 게시글 제목2", LocalDate.now(), LocalDate.now()) + ); + + assertThat(response).isEqualTo(new ArticleSummariesResponse(articles, 0, 1, 4)); + } + + @DisplayName("스터디 커뮤니티 전체 공지사항을 기본 페이징 정보로 조회한다.") + @Test + void getStudyCommunityArticlesByDefaultPageable() { + // arrange + long 스터디_ID = 그린론이().로그인하고().자바_스터디를().시작일자는(LocalDate.now()).생성한다(); + long 공지글1_ID = 그린론이().로그인하고().스터디에(스터디_ID).공지사항을_작성한다("자바 게시글 제목1", "자바 게시글 내용1"); + long 공지글2_ID = 그린론이().로그인하고().스터디에(스터디_ID).공지사항을_작성한다("자바 게시글 제목2", "자바 게시글 내용2"); + long 공지글3_ID = 그린론이().로그인하고().스터디에(스터디_ID).공지사항을_작성한다("자바 게시글 제목3", "자바 게시글 내용3"); + long 공지글4_ID = 그린론이().로그인하고().스터디에(스터디_ID).공지사항을_작성한다("자바 게시글 제목4", "자바 게시글 내용4"); + + String 토큰 = 그린론이().로그인한다(); + + // act + final ArticleSummariesResponse response = RestAssured.given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .pathParam("study-id", 스터디_ID) + .when().log().all() + .get("/api/studies/{study-id}/notice/articles") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract().as(ArticleSummariesResponse.class); + + // assert + AuthorResponse 그린론 = new AuthorResponse(그린론_깃허브_ID, 그린론_이름, 그린론_이미지_URL, 그린론_프로필_URL); + + List articles = List.of( + new ArticleSummaryResponse(공지글4_ID, 그린론, "자바 게시글 제목4", LocalDate.now(), LocalDate.now()), + new ArticleSummaryResponse(공지글3_ID, 그린론, "자바 게시글 제목3", LocalDate.now(), LocalDate.now()), + new ArticleSummaryResponse(공지글2_ID, 그린론, "자바 게시글 제목2", LocalDate.now(), LocalDate.now()), + new ArticleSummaryResponse(공지글1_ID, 그린론, "자바 게시글 제목1", LocalDate.now(), LocalDate.now()) + ); + + assertThat(response).isEqualTo(new ArticleSummariesResponse(articles, 0, 0, 4)); + } + + @DisplayName("커뮤니티 글을 수정한다.") + @Test + void updateArticleToCommunity() throws JsonProcessingException { + // arrange + long 스터디_ID = 그린론이().로그인하고().자바_스터디를().시작일자는(LocalDate.now()).생성한다(); + long 공지글_ID = 그린론이().로그인하고().스터디에(스터디_ID).공지사항을_작성한다("게시글 제목", "게시글 내용"); + String 토큰 = 그린론이().로그인한다(); + + final ArticleRequest request = new ArticleRequest("게시글 제목 수정", "게시글 내용 수정"); + + // act + RestAssured.given(spec).log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .pathParam("study-id", 스터디_ID) + .pathParam("article-id", 공지글_ID) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(objectMapper.writeValueAsString(request)) + .filter(document("update/notice", + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("JWT 토큰") + ), + pathParameters( + parameterWithName("study-id").description("스터디 식별 번호"), + parameterWithName("article-id").description("게시글 식별 번호") + ), + requestFields( + fieldWithPath("title").type(JsonFieldType.STRING).description("게시글 수정 제목"), + fieldWithPath("content").type(JsonFieldType.STRING).description("게시글 내용 수정") + ) + )) + .when().log().all() + .put("/api/studies/{study-id}/notice/articles/{article-id}") + .then().log().all() + .statusCode(HttpStatus.NO_CONTENT.value()); + + // assert + final ArticleResponse response = RestAssured + .given().log().all() + .header(HttpHeaders.AUTHORIZATION, 토큰) + .pathParam("study-id", 스터디_ID) + .pathParam("article-id", 공지글_ID) + .when().log().all() + .get("/api/studies/{study-id}/notice/articles/{article-id}") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract() + .as(ArticleResponse.class); + + final AuthorResponse authorResponse = new AuthorResponse(그린론_깃허브_ID, 그린론_이름, 그린론_이미지_URL, 그린론_프로필_URL); + + assertThat(response).isEqualTo(new ArticleResponse(스터디_ID, authorResponse, "게시글 제목 수정", + "게시글 내용 수정", LocalDate.now(), LocalDate.now())); + } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java index e115853a9..efd12a997 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java @@ -6,8 +6,11 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; import com.woowacourse.moamoa.community.domain.CommunityArticle; +import com.woowacourse.moamoa.community.domain.NoticeArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.query.CommunityArticleDao; +import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; +import com.woowacourse.moamoa.community.query.ArticleDao; +import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; @@ -42,7 +45,10 @@ public class ArticleControllerTest { private CommunityArticleRepository communityArticleRepository; @Autowired - private CommunityArticleDao communityArticleDao; + private NoticeArticleRepository noticeArticleRepository; + + @Autowired + private ArticleDao articleDao; private StudyService studyService; private ArticleController sut; @@ -51,7 +57,8 @@ public class ArticleControllerTest { void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); sut = new ArticleController(new ArticleService(memberRepository, studyRepository, - communityArticleRepository, communityArticleDao)); + articleDao, + new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository))); } @DisplayName("커뮤니티 게시글을 작성한다.") @@ -77,6 +84,29 @@ void createCommunityArticle() { .isEqualTo(new CommunityArticle(articleId, "게시글 제목", "게시글 내용", member.getId(), study)); } + @DisplayName("커뮤니티 공지사항을 작성한다.") + @Test + void createNoticeArticle() { + // arrange + Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); + Study study = studyService + .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); + + ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); + + // act + ResponseEntity response = sut.createArticle(member.getId(), study.getId(), "notice", request); + + // assert + String location = response.getHeaders().getLocation().getPath(); + Long articleId = Long.valueOf(location.replaceAll("/api/studies/\\d+/notice/articles/", "")); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); + assertThat(location).matches("/api/studies/\\d+/notice/articles/\\d+"); + assertThat(noticeArticleRepository.findById(articleId).get()) + .isEqualTo(new NoticeArticle(articleId, "게시글 제목", "게시글 내용", member.getId(), study)); + } + @DisplayName("사용자가 없는 경우 게시글 작성 시 예외가 발생한다.") @Test void throwExceptionWhenCreateByNotFoundMember() { diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java index 5c482caca..fb802a5d1 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java @@ -5,9 +5,11 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.CommunityArticle; +import com.woowacourse.moamoa.community.domain.Article; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.query.CommunityArticleDao; +import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; +import com.woowacourse.moamoa.community.query.ArticleDao; +import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; @@ -40,7 +42,10 @@ public class DeletingArticleControllerTest { private CommunityArticleRepository communityArticleRepository; @Autowired - private CommunityArticleDao communityArticleDao; + private NoticeArticleRepository noticeArticleRepository; + + @Autowired + private ArticleDao articleDao; private StudyService studyService; private ArticleController sut; @@ -50,7 +55,8 @@ public class DeletingArticleControllerTest { void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); articleService = new ArticleService(memberRepository, studyRepository, - communityArticleRepository, communityArticleDao); + articleDao, + new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); sut = new ArticleController(articleService); } @@ -64,8 +70,8 @@ void deleteCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), - request); + Article article = articleService.createArticle(member.getId(), study.getId(), + request, "community"); //act sut.deleteArticle(member.getId(), study.getId(), "community", article.getId()); @@ -98,8 +104,8 @@ void throwExceptionWhenDeletingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), - request); + final Article article = articleService.createArticle(member.getId(), study.getId(), + request, "community"); // act & assert assertThatThrownBy(() -> sut.deleteArticle(other.getId(), study.getId(), "community", article.getId())) diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java index 7174c062b..1e31f846c 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java @@ -5,9 +5,11 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.CommunityArticle; +import com.woowacourse.moamoa.community.domain.Article; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.query.CommunityArticleDao; +import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; +import com.woowacourse.moamoa.community.query.ArticleDao; +import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; @@ -44,7 +46,10 @@ public class GettingArticleControllerTest { private CommunityArticleRepository communityArticleRepository; @Autowired - private CommunityArticleDao communityArticleDao; + private NoticeArticleRepository noticeArticleRepository; + + @Autowired + private ArticleDao articleDao; private StudyService studyService; private ArticleController sut; @@ -54,7 +59,8 @@ public class GettingArticleControllerTest { void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); articleService = new ArticleService(memberRepository, studyRepository, - communityArticleRepository, communityArticleDao); + articleDao, + new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); sut = new ArticleController(articleService); } @@ -67,8 +73,8 @@ void getStudyCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), - request); + final Article article = articleService.createArticle(member.getId(), study.getId(), + request, "community"); //act final ResponseEntity response = sut.getArticle(member.getId(), study.getId(), @@ -106,8 +112,8 @@ void throwExceptionWhenGettingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), - request); + final Article article = articleService.createArticle(member.getId(), study.getId(), + request, "community"); // act & assert assertThatThrownBy(() -> sut.getArticle(other.getId(), study.getId(), "community", article.getId())) diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java index 5a5657a41..d63a2acc5 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java @@ -5,9 +5,11 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.CommunityArticle; +import com.woowacourse.moamoa.community.domain.Article; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.query.CommunityArticleDao; +import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; +import com.woowacourse.moamoa.community.query.ArticleDao; +import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; import com.woowacourse.moamoa.community.service.request.ArticleRequest; @@ -47,18 +49,22 @@ public class GettingCommunityArticleSummariesControllerTest { @Autowired private StudyRepository studyRepository; + @Autowired + private NoticeArticleRepository noticeArticleRepository; + @Autowired private CommunityArticleRepository communityArticleRepository; @Autowired - private CommunityArticleDao communityArticleDao; + private ArticleDao articleDao; private ArticleController sut; @BeforeEach void setUp() { articleService = new ArticleService(memberRepository, studyRepository, - communityArticleRepository, communityArticleDao); + articleDao, + new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); sut = new ArticleController(articleService); } @@ -71,14 +77,14 @@ void getCommunityArticles() { Study study = studyService.createStudy(그린론.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); - articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목1", "내용1")); - articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목2", "내용2")); - CommunityArticle article3 = articleService - .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목3", "내용3")); - CommunityArticle article4 = articleService - .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목4", "내용4")); - CommunityArticle article5 = articleService - .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목5", "내용5")); + articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목1", "내용1"), "community"); + articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목2", "내용2"), "community"); + Article article3 = articleService + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목3", "내용3"), "community"); + Article article4 = articleService + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목4", "내용4"), "community"); + Article article5 = articleService + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목5", "내용5"), "community"); // act ResponseEntity response = sut.getArticles(그린론.getId(), study.getId(), "community", diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java index 080c1b046..68da20827 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java @@ -5,9 +5,12 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; +import com.woowacourse.moamoa.community.domain.Article; import com.woowacourse.moamoa.community.domain.CommunityArticle; import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.query.CommunityArticleDao; +import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; +import com.woowacourse.moamoa.community.query.ArticleDao; +import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; import com.woowacourse.moamoa.community.service.ArticleService; import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; @@ -38,11 +41,14 @@ public class UpdatingArticleControllerTest { @Autowired private MemberRepository memberRepository; + @Autowired + private NoticeArticleRepository noticeArticleRepository; + @Autowired private CommunityArticleRepository communityArticleRepository; @Autowired - private CommunityArticleDao communityArticleDao; + private ArticleDao articleDao; private StudyService studyService; private ArticleController sut; @@ -52,7 +58,8 @@ public class UpdatingArticleControllerTest { void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); articleService = new ArticleService(memberRepository, studyRepository, - communityArticleRepository, communityArticleDao); + articleDao, + new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); sut = new ArticleController(articleService); } @@ -63,15 +70,15 @@ void updateArticle() { Member member = memberRepository.save(new Member(1L, "username", "image", "profile")); Study study = studyService .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); - CommunityArticle article = articleService - .createArticle(member.getId(), study.getId(), new ArticleRequest("제목", "내용")); + Article article = articleService + .createArticle(member.getId(), study.getId(), new ArticleRequest("제목", "내용"), "community"); // act final ResponseEntity response = sut.updateArticle(member.getId(), study.getId(), "community", article.getId(), new ArticleRequest("제목 수정", "내용 수정")); // assert - CommunityArticle actualArticle = communityArticleRepository.findById(article.getId()).orElseThrow(); + Article actualArticle = communityArticleRepository.findById(article.getId()).orElseThrow(); CommunityArticle expectArticle = new CommunityArticle(article.getId(), "제목 수정", "내용 수정", member.getId(), study); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); @@ -104,8 +111,8 @@ void throwExceptionWhenUpdateByNotParticipant() { .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final CommunityArticle article = articleService.createArticle(member.getId(), study.getId(), - request); + final Article article = articleService.createArticle(member.getId(), study.getId(), + request, "community"); // act & assert assertThatThrownBy(() -> sut diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java index cab877996..27ba531dd 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java @@ -33,7 +33,7 @@ void writeCommunityArticleByParticipant() { final Member another = createMember(2L); final Study study = createStudy(1L, owner); - assertThatThrownBy(() -> CommunityArticle.write(another, study, new ArticleRequest("제목", "내용"))) + assertThatThrownBy(() -> Article.write(another, study, new ArticleRequest("제목", "내용"), "community")) .isInstanceOf(NotParticipatedMemberException.class); } @@ -46,7 +46,8 @@ void getArticle(Long viewerId, boolean expected) { final Study study = createStudy(1L, owner); study.participate(participant.getId()); - final CommunityArticle communityArticle = CommunityArticle.write(owner, study, new ArticleRequest("제목", "내용")); + final Article communityArticle = Article.write(owner, study, new ArticleRequest("제목", "내용"), + "community"); assertThat(communityArticle.isViewableBy(study.getId(), viewerId)).isEqualTo(expected); } @@ -57,7 +58,8 @@ void getArticle(Long viewerId, boolean expected) { void deleteArticle(Long studyId, Long wantToViewStudyId, boolean expected) { final Member member = createMember(1L); final Study study = createStudy(studyId, member); - final CommunityArticle communityArticle = CommunityArticle.write(member, study, new ArticleRequest("제목", "내용")); + final Article communityArticle = Article.write(member, study, new ArticleRequest("제목", "내용"), + "community"); assertThat(communityArticle.isViewableBy(wantToViewStudyId, member.getId())).isEqualTo(expected); } @@ -70,7 +72,8 @@ void updateArticle(Long editorId, boolean expected) { final Member participant = createMember(2L); final Study study = createStudy(1L, owner); study.participate(participant.getId()); - final CommunityArticle communityArticle = CommunityArticle.write(owner, study, new ArticleRequest("제목", "내용")); + final Article communityArticle = Article.write(owner, study, new ArticleRequest("제목", "내용"), + "community"); assertThat(communityArticle.isEditableBy(study.getId(), editorId)).isEqualTo(expected); } @@ -80,7 +83,8 @@ void updateArticle(Long editorId, boolean expected) { void editArticleByInvalidStudyId() { final Member member = createMember(1L); final Study study = createStudy(1L, member); - final CommunityArticle communityArticle = CommunityArticle.write(member, study, new ArticleRequest("제목", "내용")); + final Article communityArticle = Article.write(member, study, new ArticleRequest("제목", "내용"), + "community"); assertThat(communityArticle.isViewableBy(2L, member.getId())).isFalse(); } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java index e7d85cfd0..30292bb77 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java @@ -146,7 +146,7 @@ void badRequestByInvalidLengthContent() throws Exception { @DisplayName("스터디에 참여한 참가자가 아닌 경우, NotParticipatedMemberException이 발생하고 401을 반환한다.") @Test void unauthorizedByNotParticipant() throws Exception { - when(articleService.createArticle(any(), any(), any())).thenThrow(NotParticipatedMemberException.class); + when(articleService.createArticle(any(), any(), any(), any())).thenThrow(NotParticipatedMemberException.class); final String token = "Bearer" + tokenProvider.createToken(1L).getAccessToken(); diff --git a/backend/src/test/resources/schema.sql b/backend/src/test/resources/schema.sql index fcbcc4936..8f4d82869 100644 --- a/backend/src/test/resources/schema.sql +++ b/backend/src/test/resources/schema.sql @@ -1,4 +1,5 @@ -DROP TABLE IF EXISTS article; +DROP TABLE IF EXISTS community; +DROP TABLE IF EXISTS notice; DROP TABLE IF EXISTS study_tag; DROP TABLE IF EXISTS study_member; DROP TABLE IF EXISTS tag; @@ -96,7 +97,20 @@ CREATE TABLE study_member FOREIGN KEY (member_id) REFERENCES member (id) ); -CREATE TABLE article +CREATE TABLE community +( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + title VARCHAR(255) NOT NULL, + content MEDIUMTEXT NOT NULL, + author_id BIGINT, + study_id BIGINT, + created_date DATETIME not null, + last_modified_date DATETIME not null, + FOREIGN KEY (author_id) REFERENCES member (id), + FOREIGN KEY (study_id) REFERENCES study (id) +); + +CREATE TABLE notice ( id BIGINT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255) NOT NULL, From dbaedbd5afc436454846a45b0632deedb27491e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=98=81?= Date: Sat, 13 Aug 2022 17:15:08 +0900 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20=EB=A0=88=ED=8F=AC=EC=A7=80?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=A0=95=EB=A6=AC=20=EB=B0=8F=20ArticleTy?= =?UTF-8?q?pe=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moamoa/community/domain/Article.java | 112 ------------------ .../domain/repository/ArticleRepository.java | 13 -- .../CommunityArticleRepository.java | 38 ------ .../JpaCommunityArticleRepository.java | 7 -- .../JpaNoticeArticleRepository.java | 7 -- .../repository/NoticeArticleRepository.java | 39 ------ .../service/ArticleRepositoryFactory.java | 32 ----- .../controller/ArticleController.java | 38 +++--- .../converter/ArticleTypeConverter.java | 14 +++ .../moamoa/studyroom/domain/Accessor.java | 20 ++++ .../moamoa/studyroom/domain/Article.java | 73 ++++++++++++ .../moamoa/studyroom/domain/ArticleType.java | 10 ++ .../domain/CommunityArticle.java | 26 +++- .../domain/NoticeArticle.java | 34 ++++-- .../domain/repository/ArticleRepository.java | 18 +++ .../repository/ArticleRepositoryFactory.java | 24 ++++ .../CommunityArticleRepository.java | 13 ++ .../repository/NoticeArticleRepository.java | 13 ++ .../query/ArticleDao.java | 31 ++--- .../query/data/ArticleData.java | 2 +- .../service/ArticleService.java | 88 +++++++------- .../exception/ArticleNotFoundException.java | 2 +- .../exception/NotArticleAuthorException.java | 2 +- .../exception/NotRelatedArticleException.java | 2 +- .../exception/UneditableArticleException.java | 2 +- .../exception/UnviewableArticleException.java | 2 +- .../service/request/ArticleRequest.java | 2 +- .../service/response/ArticleResponse.java | 4 +- .../response/ArticleSummariesResponse.java | 2 +- .../response/ArticleSummaryResponse.java | 4 +- .../service/response/AuthorResponse.java | 2 +- .../acceptance/steps/StudyRelatedSteps.java | 2 +- .../CommunityAcceptanceTest.java | 12 +- .../NoticeAcceptanceTest.java | 17 +-- .../controller/ArticleControllerTest.java | 57 ++++----- .../DeletingArticleControllerTest.java | 44 +++---- .../GettingArticleControllerTest.java | 45 +++---- ...mmunityArticleSummariesControllerTest.java | 54 ++++----- .../UpdatingArticleControllerTest.java | 59 +++++---- .../domain/CommunityArticleTest.java | 25 ++-- .../CreatingArticleControllerWebMvcTest.java | 6 +- .../DeletingArticleControllerWebMvcTest.java | 2 +- .../GettingArticleControllerWebMvcTest.java | 2 +- .../UpdatingArticleControllerWebMvcTest.java | 4 +- 44 files changed, 468 insertions(+), 537 deletions(-) delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java delete mode 100644 backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/controller/ArticleController.java (80%) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/converter/ArticleTypeConverter.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Accessor.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/ArticleType.java rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/domain/CommunityArticle.java (68%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/domain/NoticeArticle.java (69%) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/query/ArticleDao.java (81%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/query/data/ArticleData.java (93%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/ArticleService.java (50%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/exception/ArticleNotFoundException.java (82%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/exception/NotArticleAuthorException.java (84%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/exception/NotRelatedArticleException.java (84%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/exception/UneditableArticleException.java (77%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/exception/UnviewableArticleException.java (85%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/request/ArticleRequest.java (90%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/response/ArticleResponse.java (85%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/response/ArticleSummariesResponse.java (92%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/response/ArticleSummaryResponse.java (90%) rename backend/src/main/java/com/woowacourse/moamoa/{community => studyroom}/service/response/AuthorResponse.java (91%) rename backend/src/test/java/com/woowacourse/acceptance/test/{community => studyroom}/CommunityAcceptanceTest.java (98%) rename backend/src/test/java/com/woowacourse/acceptance/test/{notice => studyroom}/NoticeAcceptanceTest.java (96%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/controller/ArticleControllerTest.java (68%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/controller/DeletingArticleControllerTest.java (69%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/controller/GettingArticleControllerTest.java (72%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/controller/GettingCommunityArticleSummariesControllerTest.java (71%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/controller/UpdatingArticleControllerTest.java (65%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/domain/CommunityArticleTest.java (74%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/webmvc/CreatingArticleControllerWebMvcTest.java (97%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/webmvc/DeletingArticleControllerWebMvcTest.java (97%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/webmvc/GettingArticleControllerWebMvcTest.java (98%) rename backend/src/test/java/com/woowacourse/moamoa/{community => studyroom}/webmvc/UpdatingArticleControllerWebMvcTest.java (98%) diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java deleted file mode 100644 index ba09ecddc..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/Article.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.woowacourse.moamoa.community.domain; - -import static javax.persistence.GenerationType.IDENTITY; - -import com.woowacourse.moamoa.common.entity.BaseEntity; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.member.domain.Member; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; -import com.woowacourse.moamoa.study.domain.MemberRole; -import com.woowacourse.moamoa.study.domain.Study; -import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.MappedSuperclass; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@MappedSuperclass -@NoArgsConstructor -@Getter -public abstract class Article extends BaseEntity { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Long id; - - private String title; - - private String content; - - @Column(name = "author_id") - private Long authorId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "study_id") - private Study study; - - Article(final String title, final String content, final Long authorId, final Study study) { - this(null, title, content, authorId, study); - } - - public Article(final Long id, final String title, final String content, final Long authorId, - final Study study) { - this.id = id; - this.title = title; - this.content = content; - this.authorId = authorId; - this.study = study; - } - - public void update(final String title, final String content) { - this.title = title; - this.content = content; - } - - public boolean isViewableBy(final Long studyId, final Long memberId) { - return isBelongTo(studyId) && study.isParticipant(memberId); - } - - public boolean isEditableBy(final Long studyId, final Long memberId) { - return isViewableBy(studyId, memberId) && isAuthor(memberId); - } - - private boolean isBelongTo(final Long studyId) { - return this.study.getId().equals(studyId); - } - - private boolean isAuthor(final Long memberId) { - return this.authorId.equals(memberId); - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final CommunityArticle that = (CommunityArticle) o; - return Objects.equals(getId(), that.getId()) && Objects.equals(getTitle(), that.getTitle()) - && Objects.equals(getContent(), that.getContent()) && Objects.equals(getAuthorId(), - that.getAuthorId()) && Objects.equals(getStudy().getId(), that.getStudy().getId()); - } - - @Override - public int hashCode() { - return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudy().getId()); - } - - public static Article write(final Member member, final Study study, final ArticleRequest request, - final String articleType) { - final MemberRole role = study.getRole(member.getId()); - - if (articleType.equals("community")) { - if (role.equals(MemberRole.NON_MEMBER)) { - throw new NotParticipatedMemberException(); - } - return new CommunityArticle(request.getTitle(), request.getContent(), member.getId(), study); - } - - if (role.equals(MemberRole.OWNER)) { - return new NoticeArticle(request.getTitle(), request.getContent(), member.getId(), study); - } - - throw new NotParticipatedMemberException(); - } -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java deleted file mode 100644 index 831d9af71..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/ArticleRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.woowacourse.moamoa.community.domain.repository; - -import com.woowacourse.moamoa.community.domain.Article; -import java.util.Optional; - -public interface ArticleRepository { - - Article save(Article article); - - Optional
findById(Long id); - - void deleteById(Long id); -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java deleted file mode 100644 index fd4a0258c..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/CommunityArticleRepository.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.woowacourse.moamoa.community.domain.repository; - -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.domain.CommunityArticle; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import java.util.Optional; -import org.springframework.stereotype.Repository; - -@Repository -public class CommunityArticleRepository implements ArticleRepository { - - private final JpaCommunityArticleRepository jpaCommunityArticleRepository; - - public CommunityArticleRepository( - final JpaCommunityArticleRepository jpaCommunityArticleRepository) { - this.jpaCommunityArticleRepository = jpaCommunityArticleRepository; - } - - @Override - public Article save(Article article) { - return jpaCommunityArticleRepository.save((CommunityArticle) article); - } - - @Override - public Optional
findById(Long id) { - final CommunityArticle article = jpaCommunityArticleRepository.findById(id).orElseThrow( - () -> new ArticleNotFoundException(id)); - return Optional.of(article); - } - - public void deleteById(final Long articleId) { - jpaCommunityArticleRepository.deleteById(articleId); - } - - public boolean existsById(final Long id) { - return jpaCommunityArticleRepository.existsById(id); - } -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java deleted file mode 100644 index f1083b2f2..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaCommunityArticleRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.woowacourse.moamoa.community.domain.repository; - -import com.woowacourse.moamoa.community.domain.CommunityArticle; -import org.springframework.data.jpa.repository.JpaRepository; - -interface JpaCommunityArticleRepository extends JpaRepository { -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java deleted file mode 100644 index 834bfc198..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/JpaNoticeArticleRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.woowacourse.moamoa.community.domain.repository; - -import com.woowacourse.moamoa.community.domain.NoticeArticle; -import org.springframework.data.jpa.repository.JpaRepository; - -interface JpaNoticeArticleRepository extends JpaRepository { -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java deleted file mode 100644 index cd433bfd5..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/repository/NoticeArticleRepository.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.woowacourse.moamoa.community.domain.repository; - -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.domain.CommunityArticle; -import com.woowacourse.moamoa.community.domain.NoticeArticle; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import java.util.Optional; -import org.springframework.stereotype.Repository; - -@Repository -public class NoticeArticleRepository implements ArticleRepository { - - private final JpaNoticeArticleRepository noticeArticleRepository; - - public NoticeArticleRepository( - final JpaNoticeArticleRepository noticeArticleRepository) { - this.noticeArticleRepository = noticeArticleRepository; - } - - @Override - public Article save(Article article) { - return noticeArticleRepository.save((NoticeArticle) article); - } - - @Override - public Optional
findById(Long id) { - final NoticeArticle article = noticeArticleRepository.findById(id).orElseThrow( - () -> new ArticleNotFoundException(id)); - return Optional.of(article); - } - - public void deleteById(final Long articleId) { - noticeArticleRepository.deleteById(articleId); - } - - public boolean existsById(final Long id) { - return noticeArticleRepository.existsById(id); - } -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java b/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java deleted file mode 100644 index 62ab35c48..000000000 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleRepositoryFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.woowacourse.moamoa.community.service; - -import com.woowacourse.moamoa.community.domain.repository.ArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; -import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import org.springframework.stereotype.Component; - -@Component -public class ArticleRepositoryFactory { - - private final CommunityArticleRepository communityArticleRepository; - private final NoticeArticleRepository noticeArticleRepository; - - public ArticleRepositoryFactory( - final CommunityArticleRepository communityArticleRepository, - final NoticeArticleRepository noticeArticleRepository) { - this.communityArticleRepository = communityArticleRepository; - this.noticeArticleRepository = noticeArticleRepository; - } - - public ArticleRepository getRepository() { - return communityArticleRepository; - } - - public ArticleRepository getRepository(final String articleType) { - if (articleType.equals("community")) { - return communityArticleRepository; - } - return noticeArticleRepository; - } -} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/ArticleController.java similarity index 80% rename from backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/ArticleController.java index 91a2eefa5..435b4113b 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/controller/ArticleController.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/ArticleController.java @@ -1,11 +1,12 @@ -package com.woowacourse.moamoa.community.controller; +package com.woowacourse.moamoa.studyroom.controller; import com.woowacourse.moamoa.auth.config.AuthenticatedMember; -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.community.service.response.ArticleResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummariesResponse; import java.net.URI; import javax.validation.Valid; import org.springframework.data.domain.Pageable; @@ -34,17 +35,18 @@ public ArticleController(final ArticleService articleService) { @PostMapping public ResponseEntity createArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, - @PathVariable("article-type") final String articleType, - @Valid @RequestBody final ArticleRequest request) { - final Article article = articleService.createArticle(id, studyId, request, articleType); - final URI location = URI.create("/api/studies/" + studyId + "/" + articleType + "/articles/" + article.getId()); + @PathVariable("article-type") final ArticleType type, + @Valid @RequestBody final ArticleRequest request + ) { + final Article article = articleService.createArticle(id, studyId, request, type); + final URI location = URI.create("/api/studies/" + studyId + "/" + type.lowerName() + "/articles/" + article.getId()); return ResponseEntity.created(location).header("Access-Control-Allow-Headers", HttpHeaders.LOCATION).build(); } @GetMapping("/{article-id}") public ResponseEntity getArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, - @PathVariable("article-type") final String articleType, + @PathVariable("article-type") final ArticleType articleType, @PathVariable("article-id") final Long articleId ) { ArticleResponse response = articleService.getArticle(id, studyId, articleId, articleType); @@ -54,31 +56,31 @@ public ResponseEntity getArticle(@AuthenticatedMember final Lon @DeleteMapping("{article-id}") public ResponseEntity deleteArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, - @PathVariable("article-type") final String articleType, - @PathVariable("article-id") final Long articleId + @PathVariable("article-id") final Long articleId, + @PathVariable("article-type") final ArticleType type ) { - articleService.deleteArticle(id, studyId, articleId, articleType); + articleService.deleteArticle(id, studyId, articleId, type); return ResponseEntity.noContent().build(); } @GetMapping public ResponseEntity getArticles(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, - @PathVariable("article-type") final String articleType, + @PathVariable("article-type") final ArticleType type, @PageableDefault final Pageable pageable ) { - ArticleSummariesResponse response = articleService.getArticles(id, studyId, pageable, articleType); + ArticleSummariesResponse response = articleService.getArticles(id, studyId, pageable, type); return ResponseEntity.ok().body(response); } @PutMapping("/{article-id}") public ResponseEntity updateArticle(@AuthenticatedMember final Long id, @PathVariable("study-id") final Long studyId, - @PathVariable("article-type") final String articleType, @PathVariable("article-id") final Long articleId, + @PathVariable("article-type") final ArticleType type, @Valid @RequestBody final ArticleRequest request ) { - articleService.updateArticle(id, studyId, articleId, request, articleType); + articleService.updateArticle(id, studyId, articleId, request, type); return ResponseEntity.noContent().build(); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/converter/ArticleTypeConverter.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/converter/ArticleTypeConverter.java new file mode 100644 index 000000000..bdb8eabb8 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/controller/converter/ArticleTypeConverter.java @@ -0,0 +1,14 @@ +package com.woowacourse.moamoa.studyroom.controller.converter; + +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +@Component +public class ArticleTypeConverter implements Converter { + + @Override + public ArticleType convert(final String source) { + return ArticleType.valueOf(source.toUpperCase()); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Accessor.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Accessor.java new file mode 100644 index 000000000..9510ed9bc --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Accessor.java @@ -0,0 +1,20 @@ +package com.woowacourse.moamoa.studyroom.domain; + +public class Accessor { + + private final Long memberId; + private final Long studyId; + + public Accessor(final Long memberId, final Long studyId) { + this.memberId = memberId; + this.studyId = studyId; + } + + Long getStudyId() { + return studyId; + } + + Long getMemberId() { + return memberId; + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java new file mode 100644 index 000000000..5f7d809d1 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java @@ -0,0 +1,73 @@ +package com.woowacourse.moamoa.studyroom.domain; + +import static javax.persistence.GenerationType.IDENTITY; + +import com.woowacourse.moamoa.common.entity.BaseEntity; +import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; +import com.woowacourse.moamoa.study.domain.MemberRole; +import com.woowacourse.moamoa.study.domain.Study; +import javax.persistence.Column; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@MappedSuperclass +@NoArgsConstructor +@Getter +public abstract class Article extends BaseEntity { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @Column(name = "author_id") + private Long authorId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "study_id") + private Study study; + + public Article(final Long id, final Long authorId, final Study study) { + this.id = id; + this.authorId = authorId; + this.study = study; + } + + public boolean isViewableBy(final Accessor accessor) { + return isSameStudy(accessor) && study.isParticipant(accessor.getMemberId()); + } + + public boolean isEditableBy(final Accessor accessor) { + return isSameStudy(accessor) && isAuthor(accessor); + } + + private boolean isSameStudy(final Accessor accessor) { + return study.getId().equals(accessor.getStudyId()); + } + + private boolean isAuthor(final Accessor accessor) { + return this.authorId.equals(accessor.getMemberId()); + } + + public abstract void update(Accessor accessor, String title, String content); + + public static Article write(final Long memberId, final Study study, + final String title, final String content, final ArticleType type) { + final MemberRole role = study.getRole(memberId); + + if (type == ArticleType.COMMUNITY && !role.equals(MemberRole.NON_MEMBER)) { + return new CommunityArticle(title, content, memberId, study); + } + + if (type == ArticleType.NOTICE && role.equals(MemberRole.OWNER)) { + return new NoticeArticle(title, content, memberId, study); + } + + throw new NotParticipatedMemberException(); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/ArticleType.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/ArticleType.java new file mode 100644 index 000000000..8b299d329 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/ArticleType.java @@ -0,0 +1,10 @@ +package com.woowacourse.moamoa.studyroom.domain; + +public enum ArticleType { + + COMMUNITY, NOTICE; + + public String lowerName() { + return name().toLowerCase(); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java similarity index 68% rename from backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java index ae15c7f22..f282c50de 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/CommunityArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java @@ -1,24 +1,44 @@ -package com.woowacourse.moamoa.community.domain; +package com.woowacourse.moamoa.studyroom.domain; import com.woowacourse.moamoa.study.domain.Study; import java.util.Objects; import javax.persistence.Entity; import javax.persistence.Table; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter @Table(name = "community") public class CommunityArticle extends Article { + private String title; + + private String content; + CommunityArticle(final String title, final String content, final Long authorId, final Study study) { - super(null, title, content, authorId, study); + super(null, authorId, study); + this.title = title; + this.content = content; } public CommunityArticle(final Long id, final String title, final String content, final Long authorId, final Study study) { - super(id, title, content, authorId, study); + super(id, authorId, study); + this.title = title; + this.content = content; + } + + @Override + public void update(final Accessor accessor, final String title, final String content) { + if (!isEditableBy(accessor)) { + throw new IllegalArgumentException(); + } + + this.title = title; + this.content = content; } @Override diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java similarity index 69% rename from backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java index 4d26219ff..e7b2a691a 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/domain/NoticeArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java @@ -1,17 +1,8 @@ -package com.woowacourse.moamoa.community.domain; +package com.woowacourse.moamoa.studyroom.domain; -import static javax.persistence.GenerationType.IDENTITY; - -import com.woowacourse.moamoa.common.entity.BaseEntity; import com.woowacourse.moamoa.study.domain.Study; import java.util.Objects; -import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; import javax.persistence.Table; import lombok.AccessLevel; import lombok.Getter; @@ -19,16 +10,35 @@ @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter @Table(name = "notice") public class NoticeArticle extends Article { + private String title; + + private String content; + NoticeArticle(final String title, final String content, final Long authorId, final Study study) { - super(null, title, content, authorId, study); + super(null, authorId, study); + this.title = title; + this.content = content; } public NoticeArticle(final Long id, final String title, final String content, final Long authorId, final Study study) { - super(id, title, content, authorId, study); + super(id, authorId, study); + this.title = title; + this.content = content; + } + + @Override + public void update(final Accessor accessor, final String title, final String content) { + if (!isEditableBy(accessor)) { + throw new IllegalArgumentException(); + } + + this.title = title; + this.content = content; } @Override diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java new file mode 100644 index 000000000..fd35765bf --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java @@ -0,0 +1,18 @@ +package com.woowacourse.moamoa.studyroom.domain.repository; + +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import java.util.Optional; + +public interface ArticleRepository { + + T save(T article); + + Optional findById(Long id); + + void deleteById(Long id); + + boolean existsById(Long id); + + boolean isSupportType(ArticleType articleType); +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java new file mode 100644 index 000000000..655efa733 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java @@ -0,0 +1,24 @@ +package com.woowacourse.moamoa.studyroom.domain.repository; + +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import java.util.List; +import org.springframework.stereotype.Repository; + +@Repository +public class ArticleRepositoryFactory { + + private final List> repositories; + + public ArticleRepositoryFactory(List> repositories) { + this.repositories = repositories; + } + + @SuppressWarnings("unchecked") + public ArticleRepository
getRepository(final ArticleType articleType) { + return (ArticleRepository
) repositories.stream() + .filter(repository -> repository.isSupportType(articleType)) + .findFirst() + .orElseThrow(); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java new file mode 100644 index 000000000..0f4d6bc60 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java @@ -0,0 +1,13 @@ +package com.woowacourse.moamoa.studyroom.domain.repository; + +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; +import org.springframework.data.jpa.repository.JpaRepository; + +interface CommunityArticleRepository extends JpaRepository, ArticleRepository { + + @Override + default boolean isSupportType(ArticleType articleType) { + return articleType.equals(ArticleType.COMMUNITY); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java new file mode 100644 index 000000000..79a52d100 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java @@ -0,0 +1,13 @@ +package com.woowacourse.moamoa.studyroom.domain.repository; + +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.NoticeArticle; +import org.springframework.data.jpa.repository.JpaRepository; + +interface NoticeArticleRepository extends JpaRepository, ArticleRepository { + + @Override + default boolean isSupportType(ArticleType articleType) { + return articleType.equals(ArticleType.NOTICE); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java similarity index 81% rename from backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java index db9c2b171..1ca24f1a1 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/query/ArticleDao.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java @@ -1,6 +1,7 @@ -package com.woowacourse.moamoa.community.query; +package com.woowacourse.moamoa.studyroom.query; -import com.woowacourse.moamoa.community.query.data.ArticleData; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.query.data.ArticleData; import com.woowacourse.moamoa.member.query.data.MemberData; import java.time.LocalDate; import java.util.List; @@ -38,26 +39,24 @@ public ArticleDao(final NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; } - public Optional getById(final Long communityId, final String articleType) { + public Optional getById(final Long communityId, ArticleType type) { final String sql = "SELECT {}.id as article_id, {}.title as article_title, {}.content as article_content, " + "{}.created_date as article_created_date, {}.last_modified_date as article_last_modified_date, " + "member.github_id, member.username, member.image_url, member.profile_url " + "FROM {} JOIN member ON {}.author_id = member.id " + "WHERE {}.id = :{}Id"; - final Map params = Map.of(articleType + "Id", communityId); - return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", articleType), params, ROW_MAPPER).stream().findAny(); + final Map params = Map.of(nameOf(type) + "Id", communityId); + return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", nameOf(type)), params, ROW_MAPPER).stream().findAny(); } - public Page getAllByStudyId(final Long studyId, final Pageable pageable, - final String articleType) { - final List content = getContent(studyId, pageable, articleType); - final int totalCount = getTotalCount(studyId, articleType); + public Page getAllByStudyId(final Long studyId, final Pageable pageable, ArticleType type) { + final List content = getContent(studyId, pageable, type); + final int totalCount = getTotalCount(studyId, type); return new PageImpl<>(content, pageable, totalCount); } - private List getContent(final Long studyId, final Pageable pageable, - final String articleType) { + private List getContent(final Long studyId, final Pageable pageable, ArticleType type) { final String sql = "SELECT {}.id as article_id, {}.title as article_title, {}.content as article_content, " + "{}.created_date as article_created_date, {}.last_modified_date as article_last_modified_date, " + "member.github_id, member.username, member.image_url, member.profile_url " @@ -72,12 +71,16 @@ private List getContent(final Long studyId, final Pageable pageable "offset", pageable.getOffset() ); - return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", articleType), params, ROW_MAPPER); + return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", nameOf(type)), params, ROW_MAPPER); } - private int getTotalCount(final Long studyId, final String articleType) { + private Integer getTotalCount(final Long studyId, ArticleType type) { final String sql = "SELECT count({}.id) FROM {} WHERE {}.study_id = :studyId"; final Map param = Map.of("studyId", studyId); - return namedParameterJdbcTemplate.queryForObject(sql.replaceAll("\\{\\}", articleType), param, (rs, rn) -> rs.getInt(1)); + return namedParameterJdbcTemplate.queryForObject(sql.replaceAll("\\{\\}", nameOf(type)), param, (rs, rn) -> rs.getInt(1)); + } + + private String nameOf(final ArticleType type) { + return type.name().toLowerCase(); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/query/data/ArticleData.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/data/ArticleData.java similarity index 93% rename from backend/src/main/java/com/woowacourse/moamoa/community/query/data/ArticleData.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/query/data/ArticleData.java index 21929e2b4..a8e928bcb 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/query/data/ArticleData.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/data/ArticleData.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.query.data; +package com.woowacourse.moamoa.studyroom.query.data; import com.woowacourse.moamoa.member.query.data.MemberData; import java.time.LocalDate; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java similarity index 50% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java index 349111fbc..7581dbadf 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/ArticleService.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java @@ -1,18 +1,19 @@ -package com.woowacourse.moamoa.community.service; - -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.query.ArticleDao; -import com.woowacourse.moamoa.community.query.data.ArticleData; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; -import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.community.service.response.ArticleResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummaryResponse; -import com.woowacourse.moamoa.member.domain.Member; -import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; +package com.woowacourse.moamoa.studyroom.service; + +import com.woowacourse.moamoa.studyroom.domain.Accessor; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.query.data.ArticleData; +import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; +import com.woowacourse.moamoa.studyroom.service.exception.UneditableArticleException; +import com.woowacourse.moamoa.studyroom.service.exception.UnviewableArticleException; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummariesResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummaryResponse; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; @@ -28,85 +29,86 @@ @Transactional(readOnly = true) public class ArticleService { - private final MemberRepository memberRepository; private final StudyRepository studyRepository; + private final ArticleRepositoryFactory articleRepositoryFactory; private final ArticleDao articleDao; - private final ArticleRepositoryFactory factory; @Autowired - public ArticleService(final MemberRepository memberRepository, - final StudyRepository studyRepository, - final ArticleDao articleDao, - ArticleRepositoryFactory factory) { - this.memberRepository = memberRepository; + public ArticleService(final StudyRepository studyRepository, + final ArticleRepositoryFactory articleRepositoryFactory, + final ArticleDao articleDao) { this.studyRepository = studyRepository; + this.articleRepositoryFactory = articleRepositoryFactory; this.articleDao = articleDao; - this.factory = factory; } @Transactional public Article createArticle(final Long memberId, final Long studyId, - final ArticleRequest request, final String articleType) { - final Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + final ArticleRequest request, final ArticleType articleType) { final Study study = studyRepository.findById(studyId).orElseThrow(StudyNotFoundException::new); - - return factory.getRepository(articleType).save(Article.write(member, study, request, articleType)); + final ArticleRepository
repository = articleRepositoryFactory.getRepository(articleType); + return repository.save(Article.write(memberId, study, request.getTitle(), request.getContent(), articleType)); } public ArticleResponse getArticle(final Long memberId, final Long studyId, final Long articleId, - final String articleType) { - final Article article = factory.getRepository(articleType).findById(articleId) + final ArticleType type) { + final Article article = articleRepositoryFactory.getRepository(type) + .findById(articleId) .orElseThrow(() -> new ArticleNotFoundException(articleId)); - if (!article.isViewableBy(studyId, memberId)) { + if (!article.isViewableBy(new Accessor(memberId, studyId))) { throw new UnviewableArticleException(studyId, memberId); } - final ArticleData data = articleDao.getById(articleId, articleType) + final ArticleData data = articleDao.getById(articleId, type) .orElseThrow(() -> new ArticleNotFoundException(articleId)); return new ArticleResponse(data); } @Transactional - public void deleteArticle(final Long memberId, final Long studyId, final Long articleId, - final String articleType) { - final Article article = factory.getRepository(articleType).findById(articleId) + public void deleteArticle(final Long memberId, final Long studyId, final Long articleId, final ArticleType type) { + final Article article = articleRepositoryFactory.getRepository(type) + .findById(articleId) .orElseThrow(() -> new ArticleNotFoundException(articleId)); - if (!article.isEditableBy(studyId, memberId)) { + if (!article.isEditableBy(new Accessor(memberId, studyId))) { throw new UneditableArticleException(); } - factory.getRepository(articleType).deleteById(articleId); + articleRepositoryFactory.getRepository(type).deleteById(articleId); } public ArticleSummariesResponse getArticles(final Long memberId, final Long studyId, final Pageable pageable, - String articleType) { + final ArticleType type) { final Study study = studyRepository.findById(studyId).orElseThrow(StudyNotFoundException::new); if (!study.isParticipant(memberId)) { throw new UnviewableArticleException(studyId, memberId); } - final Page page = articleDao.getAllByStudyId(studyId, pageable, articleType); + final Page page = articleDao.getAllByStudyId(studyId, pageable, type); final List articles = page.getContent().stream() .map(ArticleSummaryResponse::new) .collect(Collectors.toList()); - return new ArticleSummariesResponse(articles, page.getNumber(), page.getTotalPages() - 1, page.getTotalElements()); + return new ArticleSummariesResponse(articles, page.getNumber(), page.getTotalPages() - 1, + page.getTotalElements()); } @Transactional public void updateArticle(final Long memberId, final Long studyId, final Long articleId, - final ArticleRequest request, final String articleType) { - final Article article = factory.getRepository(articleType).findById(articleId) + final ArticleRequest request, final ArticleType type) { + final Article article = articleRepositoryFactory.getRepository(type) + .findById(articleId) .orElseThrow(() -> new ArticleNotFoundException(articleId)); - if (!article.isEditableBy(studyId, memberId)) { + final Accessor accessor = new Accessor(memberId, studyId); + + if (!article.isEditableBy(accessor)) { throw new UneditableArticleException(); } - article.update(request.getTitle(), request.getContent()); + article.update(accessor, request.getTitle(), request.getContent()); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/ArticleNotFoundException.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/ArticleNotFoundException.java similarity index 82% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/exception/ArticleNotFoundException.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/ArticleNotFoundException.java index 5977414b7..1b54a0e02 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/ArticleNotFoundException.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/ArticleNotFoundException.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.exception; +package com.woowacourse.moamoa.studyroom.service.exception; import com.woowacourse.moamoa.common.exception.NotFoundException; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/NotArticleAuthorException.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/NotArticleAuthorException.java similarity index 84% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/exception/NotArticleAuthorException.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/NotArticleAuthorException.java index c66e9115b..4cfd4553b 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/NotArticleAuthorException.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/NotArticleAuthorException.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.exception; +package com.woowacourse.moamoa.studyroom.service.exception; import com.woowacourse.moamoa.common.exception.BadRequestException; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/NotRelatedArticleException.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/NotRelatedArticleException.java similarity index 84% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/exception/NotRelatedArticleException.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/NotRelatedArticleException.java index f66eee223..3d9726e7b 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/NotRelatedArticleException.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/NotRelatedArticleException.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.exception; +package com.woowacourse.moamoa.studyroom.service.exception; import com.woowacourse.moamoa.common.exception.BadRequestException; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/UneditableArticleException.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/UneditableArticleException.java similarity index 77% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/exception/UneditableArticleException.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/UneditableArticleException.java index 31d2cc696..552290963 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/UneditableArticleException.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/UneditableArticleException.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.exception; +package com.woowacourse.moamoa.studyroom.service.exception; import com.woowacourse.moamoa.common.exception.BadRequestException; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/UnviewableArticleException.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/UnviewableArticleException.java similarity index 85% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/exception/UnviewableArticleException.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/UnviewableArticleException.java index 875e9155f..8c39a9ff6 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/exception/UnviewableArticleException.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/exception/UnviewableArticleException.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.exception; +package com.woowacourse.moamoa.studyroom.service.exception; import com.woowacourse.moamoa.common.exception.BadRequestException; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/request/ArticleRequest.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/request/ArticleRequest.java similarity index 90% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/request/ArticleRequest.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/request/ArticleRequest.java index 97f7424f8..4c9e14518 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/request/ArticleRequest.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/request/ArticleRequest.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.request; +package com.woowacourse.moamoa.studyroom.service.request; import javax.validation.constraints.NotBlank; import lombok.Getter; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleResponse.java similarity index 85% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleResponse.java index 8f23b7e94..e8f776ea8 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleResponse.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleResponse.java @@ -1,6 +1,6 @@ -package com.woowacourse.moamoa.community.service.response; +package com.woowacourse.moamoa.studyroom.service.response; -import com.woowacourse.moamoa.community.query.data.ArticleData; +import com.woowacourse.moamoa.studyroom.query.data.ArticleData; import java.time.LocalDate; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummariesResponse.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleSummariesResponse.java similarity index 92% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummariesResponse.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleSummariesResponse.java index df05e4b65..f33df6f9d 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummariesResponse.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleSummariesResponse.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.response; +package com.woowacourse.moamoa.studyroom.service.response; import java.util.List; import lombok.EqualsAndHashCode; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleSummaryResponse.java similarity index 90% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleSummaryResponse.java index f2b252387..5e37beef5 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/ArticleSummaryResponse.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/ArticleSummaryResponse.java @@ -1,6 +1,6 @@ -package com.woowacourse.moamoa.community.service.response; +package com.woowacourse.moamoa.studyroom.service.response; -import com.woowacourse.moamoa.community.query.data.ArticleData; +import com.woowacourse.moamoa.studyroom.query.data.ArticleData; import java.time.LocalDate; import lombok.EqualsAndHashCode; import lombok.Getter; diff --git a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/AuthorResponse.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/AuthorResponse.java similarity index 91% rename from backend/src/main/java/com/woowacourse/moamoa/community/service/response/AuthorResponse.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/AuthorResponse.java index e83a5149a..7da9d9429 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/community/service/response/AuthorResponse.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/response/AuthorResponse.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.service.response; +package com.woowacourse.moamoa.studyroom.service.response; import com.woowacourse.moamoa.member.query.data.MemberData; import lombok.AllArgsConstructor; diff --git a/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java b/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java index 6fd0e95f9..9456cc359 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java +++ b/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java @@ -4,9 +4,9 @@ import static org.springframework.http.HttpHeaders.CONTENT_TYPE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.referenceroom.service.request.CreatingLinkRequest; import com.woowacourse.moamoa.review.service.request.WriteReviewRequest; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import io.restassured.RestAssured; import org.junit.jupiter.api.Assertions; import org.springframework.http.HttpHeaders; diff --git a/backend/src/test/java/com/woowacourse/acceptance/test/community/CommunityAcceptanceTest.java b/backend/src/test/java/com/woowacourse/acceptance/test/studyroom/CommunityAcceptanceTest.java similarity index 98% rename from backend/src/test/java/com/woowacourse/acceptance/test/community/CommunityAcceptanceTest.java rename to backend/src/test/java/com/woowacourse/acceptance/test/studyroom/CommunityAcceptanceTest.java index c1104bd40..978cc6baf 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/test/community/CommunityAcceptanceTest.java +++ b/backend/src/test/java/com/woowacourse/acceptance/test/studyroom/CommunityAcceptanceTest.java @@ -1,4 +1,4 @@ -package com.woowacourse.acceptance.test.community; +package com.woowacourse.acceptance.test.studyroom; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_깃허브_ID; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이름; @@ -24,11 +24,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.woowacourse.acceptance.AcceptanceTest; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.community.service.response.ArticleResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummaryResponse; -import com.woowacourse.moamoa.community.service.response.AuthorResponse; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummariesResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummaryResponse; +import com.woowacourse.moamoa.studyroom.service.response.AuthorResponse; import io.restassured.RestAssured; import java.time.LocalDate; import java.util.List; diff --git a/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java b/backend/src/test/java/com/woowacourse/acceptance/test/studyroom/NoticeAcceptanceTest.java similarity index 96% rename from backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java rename to backend/src/test/java/com/woowacourse/acceptance/test/studyroom/NoticeAcceptanceTest.java index 4fac2470f..2e5ae63e1 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/test/notice/NoticeAcceptanceTest.java +++ b/backend/src/test/java/com/woowacourse/acceptance/test/studyroom/NoticeAcceptanceTest.java @@ -1,13 +1,9 @@ -package com.woowacourse.acceptance.test.notice; +package com.woowacourse.acceptance.test.studyroom; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_깃허브_ID; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이름; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_이미지_URL; import static com.woowacourse.acceptance.fixture.MemberFixtures.그린론_프로필_URL; -import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_깃허브_ID; -import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_이름; -import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_이미지_URL; -import static com.woowacourse.acceptance.fixture.MemberFixtures.베루스_프로필_URL; import static com.woowacourse.acceptance.steps.LoginSteps.그린론이; import static com.woowacourse.acceptance.steps.LoginSteps.베루스가; import static org.assertj.core.api.Assertions.assertThat; @@ -24,16 +20,15 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.woowacourse.acceptance.AcceptanceTest; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.community.service.response.ArticleResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummaryResponse; -import com.woowacourse.moamoa.community.service.response.AuthorResponse; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummariesResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummaryResponse; +import com.woowacourse.moamoa.studyroom.service.response.AuthorResponse; import io.restassured.RestAssured; import java.time.LocalDate; import java.util.List; import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java similarity index 68% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java index efd12a997..2345df916 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/ArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java @@ -1,21 +1,19 @@ -package com.woowacourse.moamoa.community.controller; +package com.woowacourse.moamoa.studyroom.controller; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.CommunityArticle; -import com.woowacourse.moamoa.community.domain.NoticeArticle; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; -import com.woowacourse.moamoa.community.query.ArticleDao; -import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; +import com.woowacourse.moamoa.studyroom.domain.NoticeArticle; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.member.service.exception.MemberNotFoundException; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; @@ -42,10 +40,7 @@ public class ArticleControllerTest { private MemberRepository memberRepository; @Autowired - private CommunityArticleRepository communityArticleRepository; - - @Autowired - private NoticeArticleRepository noticeArticleRepository; + private ArticleRepositoryFactory articleRepositoryFactory; @Autowired private ArticleDao articleDao; @@ -56,9 +51,8 @@ public class ArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - sut = new ArticleController(new ArticleService(memberRepository, studyRepository, - articleDao, - new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository))); + sut = new ArticleController(new ArticleService(studyRepository, + articleRepositoryFactory, articleDao)); } @DisplayName("커뮤니티 게시글을 작성한다.") @@ -72,7 +66,9 @@ void createCommunityArticle() { ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); // act - ResponseEntity response = sut.createArticle(member.getId(), study.getId(), "community", request); + ResponseEntity response = sut.createArticle(member.getId(), study.getId(), + ArticleType.COMMUNITY, request + ); // assert String location = response.getHeaders().getLocation().getPath(); @@ -80,7 +76,7 @@ void createCommunityArticle() { assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(location).matches("/api/studies/\\d+/community/articles/\\d+"); - assertThat(communityArticleRepository.findById(articleId).get()) + assertThat(articleRepositoryFactory.getRepository(ArticleType.COMMUNITY).findById(articleId).get()) .isEqualTo(new CommunityArticle(articleId, "게시글 제목", "게시글 내용", member.getId(), study)); } @@ -95,7 +91,7 @@ void createNoticeArticle() { ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); // act - ResponseEntity response = sut.createArticle(member.getId(), study.getId(), "notice", request); + ResponseEntity response = sut.createArticle(member.getId(), study.getId(), ArticleType.NOTICE, request); // assert String location = response.getHeaders().getLocation().getPath(); @@ -103,25 +99,10 @@ void createNoticeArticle() { assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(location).matches("/api/studies/\\d+/notice/articles/\\d+"); - assertThat(noticeArticleRepository.findById(articleId).get()) + assertThat(articleRepositoryFactory.getRepository(ArticleType.NOTICE).findById(articleId).get()) .isEqualTo(new NoticeArticle(articleId, "게시글 제목", "게시글 내용", member.getId(), study)); } - @DisplayName("사용자가 없는 경우 게시글 작성 시 예외가 발생한다.") - @Test - void throwExceptionWhenCreateByNotFoundMember() { - // arrange - Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); - Study study = studyService - .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); - - // act & assert - assertThatThrownBy(() -> sut.createArticle(member.getId() + 1, study.getId(), "community", - new ArticleRequest("제목", "내용") - )) - .isInstanceOf(MemberNotFoundException.class); - } - @DisplayName("스터디가 없는 경우 게시글 작성 시 예외가 발생한다.") @Test void throwExceptionWhenWriteToNotFoundStudy() { @@ -129,7 +110,9 @@ void throwExceptionWhenWriteToNotFoundStudy() { Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); // act & assert - assertThatThrownBy(() -> sut.createArticle(member.getId(), 1L, "community", new ArticleRequest("제목", "내용"))) + assertThatThrownBy(() -> sut.createArticle(member.getId(), 1L, ArticleType.COMMUNITY, + new ArticleRequest("제목", "내용") + )) .isInstanceOf(StudyNotFoundException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java similarity index 69% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java index fb802a5d1..989e7d0ca 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/DeletingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java @@ -1,19 +1,18 @@ -package com.woowacourse.moamoa.community.controller; +package com.woowacourse.moamoa.studyroom.controller; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; -import com.woowacourse.moamoa.community.query.ArticleDao; -import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; +import com.woowacourse.moamoa.studyroom.service.exception.UneditableArticleException; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.study.domain.Study; @@ -39,10 +38,7 @@ public class DeletingArticleControllerTest { private MemberRepository memberRepository; @Autowired - private CommunityArticleRepository communityArticleRepository; - - @Autowired - private NoticeArticleRepository noticeArticleRepository; + private ArticleRepositoryFactory articleRepositoryFactory; @Autowired private ArticleDao articleDao; @@ -54,9 +50,8 @@ public class DeletingArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - articleService = new ArticleService(memberRepository, studyRepository, - articleDao, - new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); + articleService = new ArticleService(studyRepository, + articleRepositoryFactory, articleDao); sut = new ArticleController(articleService); } @@ -70,14 +65,13 @@ void deleteCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - Article article = articleService.createArticle(member.getId(), study.getId(), - request, "community"); + Article article = articleService.createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); //act - sut.deleteArticle(member.getId(), study.getId(), "community", article.getId()); + sut.deleteArticle(member.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY); //assert - assertThat(communityArticleRepository.existsById(article.getId())).isFalse(); + assertThat(articleRepositoryFactory.getRepository(ArticleType.COMMUNITY).existsById(article.getId())).isFalse(); } @DisplayName("게시글이 없는 경우 조회 시 예외가 발생한다.") @@ -89,7 +83,7 @@ void throwExceptionWhenGettingToNotFoundArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.deleteArticle(member.getId(), study.getId(), "community", 1L)) + assertThatThrownBy(() -> sut.deleteArticle(member.getId(), study.getId(), 1L, ArticleType.COMMUNITY)) .isInstanceOf(ArticleNotFoundException.class); } @@ -104,11 +98,11 @@ void throwExceptionWhenDeletingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final Article article = articleService.createArticle(member.getId(), study.getId(), - request, "community"); + Article article = articleService.createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); // act & assert - assertThatThrownBy(() -> sut.deleteArticle(other.getId(), study.getId(), "community", article.getId())) + assertThatThrownBy( + () -> sut.deleteArticle(other.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY)) .isInstanceOf(UneditableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java similarity index 72% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java index 1e31f846c..58106aa03 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java @@ -1,21 +1,20 @@ -package com.woowacourse.moamoa.community.controller; +package com.woowacourse.moamoa.studyroom.controller; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; -import com.woowacourse.moamoa.community.query.ArticleDao; -import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.community.service.response.ArticleResponse; -import com.woowacourse.moamoa.community.service.response.AuthorResponse; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; +import com.woowacourse.moamoa.studyroom.service.exception.UnviewableArticleException; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; +import com.woowacourse.moamoa.studyroom.service.response.AuthorResponse; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.study.domain.Study; @@ -43,10 +42,7 @@ public class GettingArticleControllerTest { private MemberRepository memberRepository; @Autowired - private CommunityArticleRepository communityArticleRepository; - - @Autowired - private NoticeArticleRepository noticeArticleRepository; + private ArticleRepositoryFactory articleRepositoryFactory; @Autowired private ArticleDao articleDao; @@ -58,9 +54,8 @@ public class GettingArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - articleService = new ArticleService(memberRepository, studyRepository, - articleDao, - new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); + articleService = new ArticleService(studyRepository, + articleRepositoryFactory, articleDao); sut = new ArticleController(articleService); } @@ -73,12 +68,11 @@ void getStudyCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final Article article = articleService.createArticle(member.getId(), study.getId(), - request, "community"); + Article article = articleService.createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); //act final ResponseEntity response = sut.getArticle(member.getId(), study.getId(), - "community", article.getId()); + ArticleType.COMMUNITY, article.getId()); //assert assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); @@ -97,7 +91,7 @@ void throwExceptionWhenGettingToNotFoundArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.getArticle(member.getId(), study.getId(), "community", 1L)) + assertThatThrownBy(() -> sut.getArticle(member.getId(), study.getId(), ArticleType.COMMUNITY, 1L)) .isInstanceOf(ArticleNotFoundException.class); } @@ -112,11 +106,10 @@ void throwExceptionWhenGettingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final Article article = articleService.createArticle(member.getId(), study.getId(), - request, "community"); + Article article = articleService.createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); // act & assert - assertThatThrownBy(() -> sut.getArticle(other.getId(), study.getId(), "community", article.getId())) + assertThatThrownBy(() -> sut.getArticle(other.getId(), study.getId(), ArticleType.COMMUNITY, article.getId())) .isInstanceOf(UnviewableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java similarity index 71% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java index d63a2acc5..0533ced3e 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/GettingCommunityArticleSummariesControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java @@ -1,21 +1,20 @@ -package com.woowacourse.moamoa.community.controller; +package com.woowacourse.moamoa.studyroom.controller; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; -import com.woowacourse.moamoa.community.query.ArticleDao; -import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.exception.UnviewableArticleException; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; -import com.woowacourse.moamoa.community.service.response.ArticleSummariesResponse; -import com.woowacourse.moamoa.community.service.response.ArticleSummaryResponse; -import com.woowacourse.moamoa.community.service.response.AuthorResponse; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.exception.UnviewableArticleException; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummariesResponse; +import com.woowacourse.moamoa.studyroom.service.response.ArticleSummaryResponse; +import com.woowacourse.moamoa.studyroom.service.response.AuthorResponse; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.study.domain.Study; @@ -50,10 +49,7 @@ public class GettingCommunityArticleSummariesControllerTest { private StudyRepository studyRepository; @Autowired - private NoticeArticleRepository noticeArticleRepository; - - @Autowired - private CommunityArticleRepository communityArticleRepository; + private ArticleRepositoryFactory articleRepositoryFactory; @Autowired private ArticleDao articleDao; @@ -62,9 +58,8 @@ public class GettingCommunityArticleSummariesControllerTest { @BeforeEach void setUp() { - articleService = new ArticleService(memberRepository, studyRepository, - articleDao, - new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); + articleService = new ArticleService(studyRepository, + articleRepositoryFactory, articleDao); studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); sut = new ArticleController(articleService); } @@ -77,18 +72,20 @@ void getCommunityArticles() { Study study = studyService.createStudy(그린론.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); - articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목1", "내용1"), "community"); - articleService.createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목2", "내용2"), "community"); + articleService + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목1", "내용1"), ArticleType.COMMUNITY); + articleService + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목2", "내용2"), ArticleType.COMMUNITY); Article article3 = articleService - .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목3", "내용3"), "community"); + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목3", "내용3"), ArticleType.COMMUNITY); Article article4 = articleService - .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목4", "내용4"), "community"); + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목4", "내용4"), ArticleType.COMMUNITY); Article article5 = articleService - .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목5", "내용5"), "community"); + .createArticle(그린론.getId(), study.getId(), new ArticleRequest("제목5", "내용5"), ArticleType.COMMUNITY); // act - ResponseEntity response = sut.getArticles(그린론.getId(), study.getId(), "community", - PageRequest.of(0, 3)); + ResponseEntity response = sut.getArticles(그린론.getId(), study.getId(), + ArticleType.COMMUNITY, PageRequest.of(0, 3)); // assert AuthorResponse author = new AuthorResponse(1L, "그린론", "http://image", "http://profile"); @@ -112,7 +109,7 @@ void throwExceptionWhenWriteToNotFoundStudy() { Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); // act & assert - assertThatThrownBy(() -> sut.getArticles(member.getId(), 1L, "community", PageRequest.of(0, 3))) + assertThatThrownBy(() -> sut.getArticles(member.getId(), 1L, ArticleType.COMMUNITY, PageRequest.of(0, 3))) .isInstanceOf(StudyNotFoundException.class); } @@ -127,7 +124,8 @@ void throwExceptionWhenGettingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.getArticles(other.getId(), study.getId(), "community", PageRequest.of(0, 3))) + assertThatThrownBy( + () -> sut.getArticles(other.getId(), study.getId(), ArticleType.COMMUNITY, PageRequest.of(0, 3))) .isInstanceOf(UnviewableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java similarity index 65% rename from backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java index 68da20827..2e05592e1 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/controller/UpdatingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java @@ -1,20 +1,19 @@ -package com.woowacourse.moamoa.community.controller; +package com.woowacourse.moamoa.studyroom.controller; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.community.domain.Article; -import com.woowacourse.moamoa.community.domain.CommunityArticle; -import com.woowacourse.moamoa.community.domain.repository.CommunityArticleRepository; -import com.woowacourse.moamoa.community.domain.repository.NoticeArticleRepository; -import com.woowacourse.moamoa.community.query.ArticleDao; -import com.woowacourse.moamoa.community.service.ArticleRepositoryFactory; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.community.service.exception.UneditableArticleException; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.ArticleType; +import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; +import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; +import com.woowacourse.moamoa.studyroom.service.exception.UneditableArticleException; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.study.domain.Study; @@ -42,10 +41,7 @@ public class UpdatingArticleControllerTest { private MemberRepository memberRepository; @Autowired - private NoticeArticleRepository noticeArticleRepository; - - @Autowired - private CommunityArticleRepository communityArticleRepository; + private ArticleRepositoryFactory articleRepositoryFactory; @Autowired private ArticleDao articleDao; @@ -57,9 +53,8 @@ public class UpdatingArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - articleService = new ArticleService(memberRepository, studyRepository, - articleDao, - new ArticleRepositoryFactory(communityArticleRepository, noticeArticleRepository)); + articleService = new ArticleService(studyRepository, + articleRepositoryFactory, articleDao); sut = new ArticleController(articleService); } @@ -71,14 +66,16 @@ void updateArticle() { Study study = studyService .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); Article article = articleService - .createArticle(member.getId(), study.getId(), new ArticleRequest("제목", "내용"), "community"); + .createArticle(member.getId(), study.getId(), new ArticleRequest("제목", "내용"), ArticleType.COMMUNITY); // act - final ResponseEntity response = sut.updateArticle(member.getId(), study.getId(), "community", article.getId(), - new ArticleRequest("제목 수정", "내용 수정")); + final ResponseEntity response = sut + .updateArticle(member.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY, + new ArticleRequest("제목 수정", "내용 수정")); // assert - Article actualArticle = communityArticleRepository.findById(article.getId()).orElseThrow(); + Article actualArticle = articleRepositoryFactory.getRepository(ArticleType.COMMUNITY).findById(article.getId()) + .orElseThrow(); CommunityArticle expectArticle = new CommunityArticle(article.getId(), "제목 수정", "내용 수정", member.getId(), study); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); @@ -94,9 +91,10 @@ void throwExceptionWhenUpdateToNotFoundArticle() { .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy( - () -> sut.updateArticle(member.getId(), study.getId(), "community", - 1L, new ArticleRequest("제목 수정", "내용 수정"))) + assertThatThrownBy(() -> + sut.updateArticle(member.getId(), study.getId(), 1L, ArticleType.COMMUNITY, + new ArticleRequest("제목 수정", "내용 수정")) + ) .isInstanceOf(ArticleNotFoundException.class); } @@ -111,13 +109,14 @@ void throwExceptionWhenUpdateByNotParticipant() { .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - final Article article = articleService.createArticle(member.getId(), study.getId(), - request, "community"); + final Article article = articleService + .createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); // act & assert - assertThatThrownBy(() -> sut - .updateArticle(other.getId(), study.getId(), "community", - article.getId(), new ArticleRequest("제목 수정", "내용 수정"))) + assertThatThrownBy(() -> + sut.updateArticle(other.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY, + new ArticleRequest("제목 수정", "내용 수정")) + ) .isInstanceOf(UneditableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java similarity index 74% rename from backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java index 27ba531dd..6ce71a2aa 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/domain/CommunityArticleTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java @@ -1,9 +1,8 @@ -package com.woowacourse.moamoa.community.domain; +package com.woowacourse.moamoa.studyroom.domain; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import com.woowacourse.moamoa.study.domain.AttachedTags; @@ -33,7 +32,7 @@ void writeCommunityArticleByParticipant() { final Member another = createMember(2L); final Study study = createStudy(1L, owner); - assertThatThrownBy(() -> Article.write(another, study, new ArticleRequest("제목", "내용"), "community")) + assertThatThrownBy(() -> Article.write(another.getId(), study, "제목", "내용", ArticleType.COMMUNITY)) .isInstanceOf(NotParticipatedMemberException.class); } @@ -46,10 +45,9 @@ void getArticle(Long viewerId, boolean expected) { final Study study = createStudy(1L, owner); study.participate(participant.getId()); - final Article communityArticle = Article.write(owner, study, new ArticleRequest("제목", "내용"), - "community"); + final Article communityArticle = Article.write(owner.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - assertThat(communityArticle.isViewableBy(study.getId(), viewerId)).isEqualTo(expected); + assertThat(communityArticle.isViewableBy(new Accessor(viewerId, study.getId()))).isEqualTo(expected); } @DisplayName("스터디에 속해 있는 게시글이 맞을 경우 조회할 수 있다.") @@ -58,10 +56,9 @@ void getArticle(Long viewerId, boolean expected) { void deleteArticle(Long studyId, Long wantToViewStudyId, boolean expected) { final Member member = createMember(1L); final Study study = createStudy(studyId, member); - final Article communityArticle = Article.write(member, study, new ArticleRequest("제목", "내용"), - "community"); + final Article communityArticle = Article.write(member.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - assertThat(communityArticle.isViewableBy(wantToViewStudyId, member.getId())).isEqualTo(expected); + assertThat(communityArticle.isViewableBy(new Accessor(member.getId(), wantToViewStudyId))).isEqualTo(expected); } @DisplayName("스터디에 참여했고, 작성자인 경우 스터디 게시글을 수정,삭제할 수 있다.") @@ -72,10 +69,9 @@ void updateArticle(Long editorId, boolean expected) { final Member participant = createMember(2L); final Study study = createStudy(1L, owner); study.participate(participant.getId()); - final Article communityArticle = Article.write(owner, study, new ArticleRequest("제목", "내용"), - "community"); + final Article communityArticle = Article.write(owner.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - assertThat(communityArticle.isEditableBy(study.getId(), editorId)).isEqualTo(expected); + assertThat(communityArticle.isEditableBy(new Accessor(editorId, study.getId()))).isEqualTo(expected); } @DisplayName("스터디에 속해 있지 않은 게시글인 경우 수정,삭제할 수 없다.") @@ -83,10 +79,9 @@ void updateArticle(Long editorId, boolean expected) { void editArticleByInvalidStudyId() { final Member member = createMember(1L); final Study study = createStudy(1L, member); - final Article communityArticle = Article.write(member, study, new ArticleRequest("제목", "내용"), - "community"); + final Article communityArticle = Article.write(member.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - assertThat(communityArticle.isViewableBy(2L, member.getId())).isFalse(); + assertThat(communityArticle.isViewableBy(new Accessor(member.getId(), 2L))).isFalse(); } private Study createStudy(final long id, final Member owner) { diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/CreatingArticleControllerWebMvcTest.java similarity index 97% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/CreatingArticleControllerWebMvcTest.java index 30292bb77..97f0e587a 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/CreatingArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/CreatingArticleControllerWebMvcTest.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.webmvc; +package com.woowacourse.moamoa.studyroom.webmvc; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -7,8 +7,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.woowacourse.moamoa.WebMVCTest; -import com.woowacourse.moamoa.community.service.ArticleService; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/DeletingArticleControllerWebMvcTest.java similarity index 97% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/DeletingArticleControllerWebMvcTest.java index b0f7cda04..4c87c82ac 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/DeletingArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/DeletingArticleControllerWebMvcTest.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.webmvc; +package com.woowacourse.moamoa.studyroom.webmvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/GettingArticleControllerWebMvcTest.java similarity index 98% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/GettingArticleControllerWebMvcTest.java index 452d4c3df..2ac43481f 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/GettingArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/GettingArticleControllerWebMvcTest.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.community.webmvc; +package com.woowacourse.moamoa.studyroom.webmvc; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; diff --git a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingArticleControllerWebMvcTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/UpdatingArticleControllerWebMvcTest.java similarity index 98% rename from backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingArticleControllerWebMvcTest.java rename to backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/UpdatingArticleControllerWebMvcTest.java index bedd1d2e3..4b131bfd0 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/community/webmvc/UpdatingArticleControllerWebMvcTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/webmvc/UpdatingArticleControllerWebMvcTest.java @@ -1,11 +1,11 @@ -package com.woowacourse.moamoa.community.webmvc; +package com.woowacourse.moamoa.studyroom.webmvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.woowacourse.moamoa.WebMVCTest; -import com.woowacourse.moamoa.community.service.request.ArticleRequest; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; From 654f8dc20e368433ea6799e7f70fd1cb09d418f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=98=81?= Date: Tue, 16 Aug 2022 11:37:51 +0900 Subject: [PATCH 4/7] =?UTF-8?q?refactor:=20PermittedParticipants=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=20(#264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: PermittedParticipants 추가 * refactor: StudyRoom, PermittedParticipants 추출 --- .../entity/ReadOnlyCollectionPersister.java | 23 ++++ .../moamoa/studyroom/domain/Article.java | 31 ++---- .../studyroom/domain/CommunityArticle.java | 14 +-- .../studyroom/domain/NoticeArticle.java | 14 +-- .../domain/PermittedParticipants.java | 44 ++++++++ .../moamoa/studyroom/domain/StudyRoom.java | 68 ++++++++++++ .../{ => article}/ArticleRepository.java | 2 +- .../ArticleRepositoryFactory.java | 2 +- .../CommunityArticleRepository.java | 2 +- .../NoticeArticleRepository.java | 2 +- .../studyroom/JpaStudyRoomRepository.java | 7 ++ .../studyroom/StudyRoomRepository.java | 9 ++ .../studyroom/service/ArticleService.java | 26 +++-- .../controller/ArticleControllerTest.java | 59 ++++++---- .../DeletingArticleControllerTest.java | 37 ++++--- .../GettingArticleControllerTest.java | 31 +++--- ...mmunityArticleSummariesControllerTest.java | 8 +- .../UpdatingArticleControllerTest.java | 40 ++++--- .../moamoa/studyroom/domain/ArticleTest.java | 90 ++++++++++++++++ .../domain/CommunityArticleTest.java | 101 ------------------ 20 files changed, 392 insertions(+), 218 deletions(-) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/common/entity/ReadOnlyCollectionPersister.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/PermittedParticipants.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/StudyRoom.java rename backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/{ => article}/ArticleRepository.java (84%) rename backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/{ => article}/ArticleRepositoryFactory.java (92%) rename backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/{ => article}/CommunityArticleRepository.java (86%) rename backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/{ => article}/NoticeArticleRepository.java (86%) create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/JpaStudyRoomRepository.java create mode 100644 backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/StudyRoomRepository.java create mode 100644 backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/ArticleTest.java delete mode 100644 backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java diff --git a/backend/src/main/java/com/woowacourse/moamoa/common/entity/ReadOnlyCollectionPersister.java b/backend/src/main/java/com/woowacourse/moamoa/common/entity/ReadOnlyCollectionPersister.java new file mode 100644 index 000000000..25547d936 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/common/entity/ReadOnlyCollectionPersister.java @@ -0,0 +1,23 @@ +package com.woowacourse.moamoa.common.entity; + +import org.hibernate.MappingException; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.access.CollectionDataAccess; +import org.hibernate.mapping.Collection; +import org.hibernate.persister.collection.BasicCollectionPersister; +import org.hibernate.persister.spi.PersisterCreationContext; + +public class ReadOnlyCollectionPersister extends BasicCollectionPersister { + + public ReadOnlyCollectionPersister(final Collection collectionBinding, + final CollectionDataAccess cacheAccessStrategy, + final PersisterCreationContext creationContext) + throws MappingException, CacheException { + super(asInverse(collectionBinding), cacheAccessStrategy, creationContext); + } + + private static Collection asInverse(Collection collection) { + collection.setInverse(true); + return collection; + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java index 5f7d809d1..a31c5bba9 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java @@ -4,8 +4,6 @@ import com.woowacourse.moamoa.common.entity.BaseEntity; import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; -import com.woowacourse.moamoa.study.domain.MemberRole; -import com.woowacourse.moamoa.study.domain.Study; import javax.persistence.Column; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; @@ -28,26 +26,22 @@ public abstract class Article extends BaseEntity { @Column(name = "author_id") private Long authorId; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "study_id") - private Study study; + private StudyRoom studyRoom; - public Article(final Long id, final Long authorId, final Study study) { + public Article(final Long id, final Long authorId, StudyRoom studyRoom) { this.id = id; this.authorId = authorId; - this.study = study; + this.studyRoom = studyRoom; } public boolean isViewableBy(final Accessor accessor) { - return isSameStudy(accessor) && study.isParticipant(accessor.getMemberId()); + return studyRoom.isPermittedAccessor(accessor); } public boolean isEditableBy(final Accessor accessor) { - return isSameStudy(accessor) && isAuthor(accessor); - } - - private boolean isSameStudy(final Accessor accessor) { - return study.getId().equals(accessor.getStudyId()); + return studyRoom.isPermittedAccessor(accessor) && isAuthor(accessor); } private boolean isAuthor(final Accessor accessor) { @@ -56,16 +50,13 @@ private boolean isAuthor(final Accessor accessor) { public abstract void update(Accessor accessor, String title, String content); - public static Article write(final Long memberId, final Study study, - final String title, final String content, final ArticleType type) { - final MemberRole role = study.getRole(memberId); - - if (type == ArticleType.COMMUNITY && !role.equals(MemberRole.NON_MEMBER)) { - return new CommunityArticle(title, content, memberId, study); + public Article write(final Accessor accessor, final StudyRoom studyRoom, final String title, final String content, final ArticleType type) { + if (type == ArticleType.COMMUNITY && studyRoom.isPermittedAccessor(accessor)) { + return new CommunityArticle(title, content, accessor.getMemberId(), studyRoom); } - if (type == ArticleType.NOTICE && role.equals(MemberRole.OWNER)) { - return new NoticeArticle(title, content, memberId, study); + if (type == ArticleType.NOTICE && studyRoom.isOwner(accessor)) { + return new NoticeArticle(title, content, accessor.getMemberId(), studyRoom); } throw new NotParticipatedMemberException(); diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java index f282c50de..e994e3df5 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java @@ -1,6 +1,5 @@ package com.woowacourse.moamoa.studyroom.domain; -import com.woowacourse.moamoa.study.domain.Study; import java.util.Objects; import javax.persistence.Entity; import javax.persistence.Table; @@ -18,15 +17,16 @@ public class CommunityArticle extends Article { private String content; - CommunityArticle(final String title, final String content, final Long authorId, final Study study) { - super(null, authorId, study); + CommunityArticle(final String title, final String content, final Long authorId, + final StudyRoom studyRoom) { + super(null, authorId, studyRoom); this.title = title; this.content = content; } public CommunityArticle(final Long id, final String title, final String content, final Long authorId, - final Study study) { - super(id, authorId, study); + final StudyRoom studyRoom) { + super(id, authorId, studyRoom); this.title = title; this.content = content; } @@ -52,11 +52,11 @@ public boolean equals(final Object o) { final CommunityArticle that = (CommunityArticle) o; return Objects.equals(getId(), that.getId()) && Objects.equals(getTitle(), that.getTitle()) && Objects.equals(getContent(), that.getContent()) && Objects.equals(getAuthorId(), - that.getAuthorId()) && Objects.equals(getStudy().getId(), that.getStudy().getId()); + that.getAuthorId()) && Objects.equals(getStudyRoom(), that.getStudyRoom()); } @Override public int hashCode() { - return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudy().getId()); + return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudyRoom()); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java index e7b2a691a..2949f69e5 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java @@ -1,6 +1,5 @@ package com.woowacourse.moamoa.studyroom.domain; -import com.woowacourse.moamoa.study.domain.Study; import java.util.Objects; import javax.persistence.Entity; import javax.persistence.Table; @@ -18,15 +17,16 @@ public class NoticeArticle extends Article { private String content; - NoticeArticle(final String title, final String content, final Long authorId, final Study study) { - super(null, authorId, study); + NoticeArticle(final String title, final String content, final Long authorId, + final StudyRoom studyRoom) { + super(null, authorId, studyRoom); this.title = title; this.content = content; } public NoticeArticle(final Long id, final String title, final String content, final Long authorId, - final Study study) { - super(id, authorId, study); + final StudyRoom studyRoom) { + super(id, authorId, studyRoom); this.title = title; this.content = content; } @@ -52,11 +52,11 @@ public boolean equals(final Object o) { final NoticeArticle that = (NoticeArticle) o; return Objects.equals(getId(), that.getId()) && Objects.equals(getTitle(), that.getTitle()) && Objects.equals(getContent(), that.getContent()) && Objects.equals(getAuthorId(), - that.getAuthorId()) && Objects.equals(getStudy().getId(), that.getStudy().getId()); + that.getAuthorId()) && Objects.equals(getStudyRoom(), that.getStudyRoom()); } @Override public int hashCode() { - return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudy().getId()); + return Objects.hash(getId(), getTitle(), getContent(), getAuthorId(), getStudyRoom()); } } diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/PermittedParticipants.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/PermittedParticipants.java new file mode 100644 index 000000000..1916a1127 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/PermittedParticipants.java @@ -0,0 +1,44 @@ +package com.woowacourse.moamoa.studyroom.domain; + +import com.woowacourse.moamoa.common.entity.ReadOnlyCollectionPersister; +import com.woowacourse.moamoa.studyroom.domain.Accessor; +import java.util.Set; +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Embeddable; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Persister; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Embeddable +public class PermittedParticipants { + + @Column(name = "owner_id", nullable = false, updatable = false, insertable = false) + private Long ownerId; + + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable( + name = "study_member", + joinColumns = @JoinColumn(name = "study_id", updatable = false, insertable = false) + ) + @Column(name = "member_id", updatable = false, insertable = false) + @Persister(impl = ReadOnlyCollectionPersister.class) + private Set participants; + + public PermittedParticipants(final Long ownerId, final Set participants) { + this.ownerId = ownerId; + this.participants = participants; + } + + boolean isOwner(final Accessor accessor) { + return ownerId.equals(accessor.getMemberId()); + } + + boolean isPermittedAccessor(final Accessor accessor) { + return isOwner(accessor) || participants.contains(accessor.getMemberId()); + } +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/StudyRoom.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/StudyRoom.java new file mode 100644 index 000000000..588428dd7 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/StudyRoom.java @@ -0,0 +1,68 @@ +package com.woowacourse.moamoa.studyroom.domain; + +import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; +import java.util.Objects; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "study") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class StudyRoom { + + @Id + @Column(name = "id", updatable = false, insertable = false) + private Long studyId; + + @Embedded + private PermittedParticipants permittedParticipants; + + public StudyRoom(Long studyId, Long ownerId, Set participants) { + this.studyId = studyId; + this.permittedParticipants = new PermittedParticipants(ownerId, participants); + } + + boolean isOwner(final Accessor accessor) { + return studyId.equals(accessor.getStudyId()) && permittedParticipants.isOwner(accessor); + } + + public boolean isPermittedAccessor(final Accessor accessor) { + return studyId.equals(accessor.getStudyId()) && permittedParticipants.isPermittedAccessor(accessor); + } + + public Article write(final Accessor accessor, final String title, final String content, final ArticleType type) { + if (type == ArticleType.COMMUNITY && isPermittedAccessor(accessor)) { + return new CommunityArticle(title, content, accessor.getMemberId(), this); + } + + if (type == ArticleType.NOTICE && isOwner(accessor)) { + return new NoticeArticle(title, content, accessor.getMemberId(), this); + } + + throw new NotParticipatedMemberException(); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final StudyRoom that = (StudyRoom) o; + return Objects.equals(studyId, that.studyId); + } + + @Override + public int hashCode() { + return Objects.hash(studyId); + } + +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/ArticleRepository.java similarity index 84% rename from backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/ArticleRepository.java index fd35765bf..3ad14b61d 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepository.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/ArticleRepository.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.studyroom.domain.repository; +package com.woowacourse.moamoa.studyroom.domain.repository.article; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/ArticleRepositoryFactory.java similarity index 92% rename from backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/ArticleRepositoryFactory.java index 655efa733..a8f159507 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/ArticleRepositoryFactory.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/ArticleRepositoryFactory.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.studyroom.domain.repository; +package com.woowacourse.moamoa.studyroom.domain.repository.article; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/CommunityArticleRepository.java similarity index 86% rename from backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/CommunityArticleRepository.java index 0f4d6bc60..a5e789b74 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/CommunityArticleRepository.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/CommunityArticleRepository.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.studyroom.domain.repository; +package com.woowacourse.moamoa.studyroom.domain.repository.article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/NoticeArticleRepository.java similarity index 86% rename from backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java rename to backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/NoticeArticleRepository.java index 79a52d100..a369ce1eb 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/NoticeArticleRepository.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/article/NoticeArticleRepository.java @@ -1,4 +1,4 @@ -package com.woowacourse.moamoa.studyroom.domain.repository; +package com.woowacourse.moamoa.studyroom.domain.repository.article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; import com.woowacourse.moamoa.studyroom.domain.NoticeArticle; diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/JpaStudyRoomRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/JpaStudyRoomRepository.java new file mode 100644 index 000000000..055093d81 --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/JpaStudyRoomRepository.java @@ -0,0 +1,7 @@ +package com.woowacourse.moamoa.studyroom.domain.repository.studyroom; + +import com.woowacourse.moamoa.studyroom.domain.StudyRoom; +import org.springframework.data.jpa.repository.JpaRepository; + +interface JpaStudyRoomRepository extends JpaRepository, StudyRoomRepository { +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/StudyRoomRepository.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/StudyRoomRepository.java new file mode 100644 index 000000000..b9901962b --- /dev/null +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/repository/studyroom/StudyRoomRepository.java @@ -0,0 +1,9 @@ +package com.woowacourse.moamoa.studyroom.domain.repository.studyroom; + +import com.woowacourse.moamoa.studyroom.domain.StudyRoom; +import java.util.Optional; + +public interface StudyRoomRepository { + + Optional findByStudyId(Long studyId); +} diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java index 7581dbadf..66b86dbfa 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/service/ArticleService.java @@ -3,8 +3,10 @@ import com.woowacourse.moamoa.studyroom.domain.Accessor; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepository; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.domain.StudyRoom; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; import com.woowacourse.moamoa.studyroom.query.ArticleDao; import com.woowacourse.moamoa.studyroom.query.data.ArticleData; import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; @@ -14,8 +16,6 @@ import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; import com.woowacourse.moamoa.studyroom.service.response.ArticleSummariesResponse; import com.woowacourse.moamoa.studyroom.service.response.ArticleSummaryResponse; -import com.woowacourse.moamoa.study.domain.Study; -import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import java.util.List; import java.util.stream.Collectors; @@ -29,15 +29,15 @@ @Transactional(readOnly = true) public class ArticleService { - private final StudyRepository studyRepository; + private final StudyRoomRepository studyRoomRepository; private final ArticleRepositoryFactory articleRepositoryFactory; private final ArticleDao articleDao; @Autowired - public ArticleService(final StudyRepository studyRepository, + public ArticleService(final StudyRoomRepository studyRoomRepository, final ArticleRepositoryFactory articleRepositoryFactory, final ArticleDao articleDao) { - this.studyRepository = studyRepository; + this.studyRoomRepository = studyRoomRepository; this.articleRepositoryFactory = articleRepositoryFactory; this.articleDao = articleDao; } @@ -45,9 +45,12 @@ public ArticleService(final StudyRepository studyRepository, @Transactional public Article createArticle(final Long memberId, final Long studyId, final ArticleRequest request, final ArticleType articleType) { - final Study study = studyRepository.findById(studyId).orElseThrow(StudyNotFoundException::new); + final StudyRoom studyRoom = studyRoomRepository.findByStudyId(studyId) + .orElseThrow(StudyNotFoundException::new); + final Accessor accessor = new Accessor(memberId, studyId); + final Article article = studyRoom.write(accessor, request.getTitle(), request.getContent(), articleType); final ArticleRepository
repository = articleRepositoryFactory.getRepository(articleType); - return repository.save(Article.write(memberId, study, request.getTitle(), request.getContent(), articleType)); + return repository.save(article); } public ArticleResponse getArticle(final Long memberId, final Long studyId, final Long articleId, @@ -80,9 +83,10 @@ public void deleteArticle(final Long memberId, final Long studyId, final Long ar public ArticleSummariesResponse getArticles(final Long memberId, final Long studyId, final Pageable pageable, final ArticleType type) { - final Study study = studyRepository.findById(studyId).orElseThrow(StudyNotFoundException::new); + final StudyRoom studyRoom = studyRoomRepository.findByStudyId(studyId) + .orElseThrow(StudyNotFoundException::new); - if (!study.isParticipant(memberId)) { + if (!studyRoom.isPermittedAccessor(new Accessor(memberId, studyId))) { throw new UnviewableArticleException(studyId, memberId); } diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java index 2345df916..7c0ddad92 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java @@ -1,17 +1,12 @@ package com.woowacourse.moamoa.studyroom.controller; +import static com.woowacourse.moamoa.studyroom.domain.ArticleType.COMMUNITY; +import static com.woowacourse.moamoa.studyroom.domain.ArticleType.NOTICE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.studyroom.domain.ArticleType; -import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; -import com.woowacourse.moamoa.studyroom.domain.NoticeArticle; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; -import com.woowacourse.moamoa.studyroom.query.ArticleDao; -import com.woowacourse.moamoa.studyroom.service.ArticleService; -import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.study.domain.Study; @@ -19,7 +14,17 @@ import com.woowacourse.moamoa.study.service.StudyService; import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; +import com.woowacourse.moamoa.studyroom.domain.NoticeArticle; +import com.woowacourse.moamoa.studyroom.domain.StudyRoom; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import java.time.LocalDate; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -42,6 +47,9 @@ public class ArticleControllerTest { @Autowired private ArticleRepositoryFactory articleRepositoryFactory; + @Autowired + private StudyRoomRepository studyRoomRepository; + @Autowired private ArticleDao articleDao; @@ -51,56 +59,63 @@ public class ArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - sut = new ArticleController(new ArticleService(studyRepository, - articleRepositoryFactory, articleDao)); + sut = new ArticleController( + new ArticleService(studyRoomRepository, articleRepositoryFactory, articleDao)); } @DisplayName("커뮤니티 게시글을 작성한다.") @Test void createCommunityArticle() { // arrange - Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); + Member owner = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); Study study = studyService - .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); + .createStudy(owner.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); // act - ResponseEntity response = sut.createArticle(member.getId(), study.getId(), - ArticleType.COMMUNITY, request - ); + ResponseEntity response = sut.createArticle(owner.getId(), study.getId(), COMMUNITY, request); // assert String location = response.getHeaders().getLocation().getPath(); Long articleId = Long.valueOf(location.replaceAll("/api/studies/\\d+/community/articles/", "")); + Article actualArticle = articleRepositoryFactory.getRepository(COMMUNITY).findById(articleId) + .orElseThrow(); + StudyRoom expectStudyRoom = new StudyRoom(study.getId(), owner.getId(), Set.of()); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(location).matches("/api/studies/\\d+/community/articles/\\d+"); - assertThat(articleRepositoryFactory.getRepository(ArticleType.COMMUNITY).findById(articleId).get()) - .isEqualTo(new CommunityArticle(articleId, "게시글 제목", "게시글 내용", member.getId(), study)); + assertThat(actualArticle).isEqualTo( + new CommunityArticle(articleId, "게시글 제목", "게시글 내용", owner.getId(), expectStudyRoom) + ); } @DisplayName("커뮤니티 공지사항을 작성한다.") @Test void createNoticeArticle() { // arrange - Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); + Member owner = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); Study study = studyService - .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); + .createStudy(owner.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); // act - ResponseEntity response = sut.createArticle(member.getId(), study.getId(), ArticleType.NOTICE, request); + ResponseEntity response = sut.createArticle(owner.getId(), study.getId(), NOTICE, request); // assert String location = response.getHeaders().getLocation().getPath(); Long articleId = Long.valueOf(location.replaceAll("/api/studies/\\d+/notice/articles/", "")); + Article actualArticle = articleRepositoryFactory.getRepository(NOTICE).findById(articleId).orElseThrow(); + + StudyRoom expectStudyRoom = new StudyRoom(study.getId(), owner.getId(), Set.of()); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(location).matches("/api/studies/\\d+/notice/articles/\\d+"); - assertThat(articleRepositoryFactory.getRepository(ArticleType.NOTICE).findById(articleId).get()) - .isEqualTo(new NoticeArticle(articleId, "게시글 제목", "게시글 내용", member.getId(), study)); + assertThat(actualArticle).isEqualTo( + new NoticeArticle(articleId, "게시글 제목", "게시글 내용", owner.getId(), expectStudyRoom) + ); } @DisplayName("스터디가 없는 경우 게시글 작성 시 예외가 발생한다.") @@ -110,7 +125,7 @@ void throwExceptionWhenWriteToNotFoundStudy() { Member member = memberRepository.save(new Member(1L, "username", "imageUrl", "profileUrl")); // act & assert - assertThatThrownBy(() -> sut.createArticle(member.getId(), 1L, ArticleType.COMMUNITY, + assertThatThrownBy(() -> sut.createArticle(member.getId(), 1L, COMMUNITY, new ArticleRequest("제목", "내용") )) .isInstanceOf(StudyNotFoundException.class); diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java index 989e7d0ca..930449664 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/DeletingArticleControllerTest.java @@ -1,24 +1,26 @@ package com.woowacourse.moamoa.studyroom.controller; +import static com.woowacourse.moamoa.studyroom.domain.ArticleType.COMMUNITY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; -import com.woowacourse.moamoa.studyroom.domain.Article; -import com.woowacourse.moamoa.studyroom.domain.ArticleType; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; -import com.woowacourse.moamoa.studyroom.query.ArticleDao; -import com.woowacourse.moamoa.studyroom.service.ArticleService; -import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; -import com.woowacourse.moamoa.studyroom.service.exception.UneditableArticleException; -import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.member.domain.Member; import com.woowacourse.moamoa.member.domain.repository.MemberRepository; import com.woowacourse.moamoa.study.domain.Study; import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; +import com.woowacourse.moamoa.studyroom.domain.Article; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.query.ArticleDao; +import com.woowacourse.moamoa.studyroom.service.ArticleService; +import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; +import com.woowacourse.moamoa.studyroom.service.exception.UneditableArticleException; +import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import java.time.LocalDate; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -34,6 +36,9 @@ public class DeletingArticleControllerTest { @Autowired private StudyRepository studyRepository; + @Autowired + private StudyRoomRepository studyRoomRepository; + @Autowired private MemberRepository memberRepository; @@ -50,7 +55,7 @@ public class DeletingArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - articleService = new ArticleService(studyRepository, + articleService = new ArticleService(studyRoomRepository, articleRepositoryFactory, articleDao); sut = new ArticleController(articleService); } @@ -65,13 +70,14 @@ void deleteCommunityArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - Article article = articleService.createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); + Article article = articleService.createArticle(member.getId(), study.getId(), request, COMMUNITY); //act - sut.deleteArticle(member.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY); + sut.deleteArticle(member.getId(), study.getId(), article.getId(), COMMUNITY); //assert - assertThat(articleRepositoryFactory.getRepository(ArticleType.COMMUNITY).existsById(article.getId())).isFalse(); + ArticleRepository
articleRepository = articleRepositoryFactory.getRepository(COMMUNITY); + assertThat(articleRepository.existsById(article.getId())).isFalse(); } @DisplayName("게시글이 없는 경우 조회 시 예외가 발생한다.") @@ -83,7 +89,7 @@ void throwExceptionWhenGettingToNotFoundArticle() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); // act & assert - assertThatThrownBy(() -> sut.deleteArticle(member.getId(), study.getId(), 1L, ArticleType.COMMUNITY)) + assertThatThrownBy(() -> sut.deleteArticle(member.getId(), study.getId(), 1L, COMMUNITY)) .isInstanceOf(ArticleNotFoundException.class); } @@ -98,11 +104,10 @@ void throwExceptionWhenDeletingByNotParticipant() { .createStudy(member.getGithubId(), javaStudyRequest.startDate(LocalDate.now()).build()); ArticleRequest request = new ArticleRequest("게시글 제목", "게시글 내용"); - Article article = articleService.createArticle(member.getId(), study.getId(), request, ArticleType.COMMUNITY); + Article article = articleService.createArticle(member.getId(), study.getId(), request, COMMUNITY); // act & assert - assertThatThrownBy( - () -> sut.deleteArticle(other.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY)) + assertThatThrownBy(() -> sut.deleteArticle(other.getId(), study.getId(), article.getId(), COMMUNITY)) .isInstanceOf(UneditableArticleException.class); } } diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java index 58106aa03..4a69ca05f 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingArticleControllerTest.java @@ -5,9 +5,16 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; +import com.woowacourse.moamoa.member.domain.Member; +import com.woowacourse.moamoa.member.domain.repository.MemberRepository; +import com.woowacourse.moamoa.study.domain.Study; +import com.woowacourse.moamoa.study.domain.repository.StudyRepository; +import com.woowacourse.moamoa.study.service.StudyService; +import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; import com.woowacourse.moamoa.studyroom.query.ArticleDao; import com.woowacourse.moamoa.studyroom.service.ArticleService; import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; @@ -15,12 +22,6 @@ import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; import com.woowacourse.moamoa.studyroom.service.response.ArticleResponse; import com.woowacourse.moamoa.studyroom.service.response.AuthorResponse; -import com.woowacourse.moamoa.member.domain.Member; -import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.study.domain.Study; -import com.woowacourse.moamoa.study.domain.repository.StudyRepository; -import com.woowacourse.moamoa.study.service.StudyService; -import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import java.time.LocalDate; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -38,6 +39,9 @@ public class GettingArticleControllerTest { @Autowired private StudyRepository studyRepository; + @Autowired + private StudyRoomRepository studyRoomRepository; + @Autowired private MemberRepository memberRepository; @@ -54,8 +58,7 @@ public class GettingArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - articleService = new ArticleService(studyRepository, - articleRepositoryFactory, articleDao); + articleService = new ArticleService(studyRoomRepository, articleRepositoryFactory, articleDao); sut = new ArticleController(articleService); } @@ -75,11 +78,13 @@ void getStudyCommunityArticle() { ArticleType.COMMUNITY, article.getId()); //assert + final AuthorResponse expectedAuthorResponse = new AuthorResponse( + member.getGithubId(), member.getUsername(), member.getImageUrl(), member.getProfileUrl() + ); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).isEqualTo(new ArticleResponse(article.getId(), - new AuthorResponse(member.getGithubId(), member.getUsername(), member.getImageUrl(), - member.getProfileUrl()), - request.getTitle(), request.getContent(), LocalDate.now(), LocalDate.now())); + assertThat(response.getBody()).isEqualTo( + new ArticleResponse(article.getId(), expectedAuthorResponse, request.getTitle(), request.getContent(), + LocalDate.now(), LocalDate.now())); } @DisplayName("게시글이 없는 경우 조회 시 예외가 발생한다.") diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java index 0533ced3e..c1450084e 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/GettingCommunityArticleSummariesControllerTest.java @@ -7,7 +7,8 @@ import com.woowacourse.moamoa.common.utils.DateTimeSystem; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; import com.woowacourse.moamoa.studyroom.query.ArticleDao; import com.woowacourse.moamoa.studyroom.service.ArticleService; import com.woowacourse.moamoa.studyroom.service.exception.UnviewableArticleException; @@ -45,6 +46,9 @@ public class GettingCommunityArticleSummariesControllerTest { @Autowired private MemberRepository memberRepository; + @Autowired + private StudyRoomRepository studyRoomRepository; + @Autowired private StudyRepository studyRepository; @@ -58,7 +62,7 @@ public class GettingCommunityArticleSummariesControllerTest { @BeforeEach void setUp() { - articleService = new ArticleService(studyRepository, + articleService = new ArticleService(studyRoomRepository, articleRepositoryFactory, articleDao); studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); sut = new ArticleController(articleService); diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java index 2e05592e1..920f56d2d 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/UpdatingArticleControllerTest.java @@ -5,22 +5,26 @@ import com.woowacourse.moamoa.common.RepositoryTest; import com.woowacourse.moamoa.common.utils.DateTimeSystem; +import com.woowacourse.moamoa.member.domain.Member; +import com.woowacourse.moamoa.member.domain.repository.MemberRepository; +import com.woowacourse.moamoa.study.domain.Study; +import com.woowacourse.moamoa.study.domain.repository.StudyRepository; +import com.woowacourse.moamoa.study.service.StudyService; +import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.ArticleType; import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; -import com.woowacourse.moamoa.studyroom.domain.repository.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.domain.StudyRoom; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepository; +import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; import com.woowacourse.moamoa.studyroom.query.ArticleDao; import com.woowacourse.moamoa.studyroom.service.ArticleService; import com.woowacourse.moamoa.studyroom.service.exception.ArticleNotFoundException; import com.woowacourse.moamoa.studyroom.service.exception.UneditableArticleException; import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; -import com.woowacourse.moamoa.member.domain.Member; -import com.woowacourse.moamoa.member.domain.repository.MemberRepository; -import com.woowacourse.moamoa.study.domain.Study; -import com.woowacourse.moamoa.study.domain.repository.StudyRepository; -import com.woowacourse.moamoa.study.service.StudyService; -import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; import java.time.LocalDate; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -37,6 +41,9 @@ public class UpdatingArticleControllerTest { @Autowired private StudyRepository studyRepository; + @Autowired + private StudyRoomRepository studyRoomRepository; + @Autowired private MemberRepository memberRepository; @@ -53,7 +60,7 @@ public class UpdatingArticleControllerTest { @BeforeEach void setUp() { studyService = new StudyService(studyRepository, memberRepository, new DateTimeSystem()); - articleService = new ArticleService(studyRepository, + articleService = new ArticleService(studyRoomRepository, articleRepositoryFactory, articleDao); sut = new ArticleController(articleService); } @@ -62,21 +69,24 @@ void setUp() { @Test void updateArticle() { // arrange - Member member = memberRepository.save(new Member(1L, "username", "image", "profile")); + Member owner = memberRepository.save(new Member(1L, "username", "image", "profile")); Study study = studyService - .createStudy(member.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); + .createStudy(owner.getGithubId(), javaStudyBuilder.startDate(LocalDate.now()).build()); Article article = articleService - .createArticle(member.getId(), study.getId(), new ArticleRequest("제목", "내용"), ArticleType.COMMUNITY); + .createArticle(owner.getId(), study.getId(), new ArticleRequest("제목", "내용"), ArticleType.COMMUNITY); // act final ResponseEntity response = sut - .updateArticle(member.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY, + .updateArticle(owner.getId(), study.getId(), article.getId(), ArticleType.COMMUNITY, new ArticleRequest("제목 수정", "내용 수정")); // assert - Article actualArticle = articleRepositoryFactory.getRepository(ArticleType.COMMUNITY).findById(article.getId()) - .orElseThrow(); - CommunityArticle expectArticle = new CommunityArticle(article.getId(), "제목 수정", "내용 수정", member.getId(), study); + ArticleRepository
articleRepository = articleRepositoryFactory.getRepository(ArticleType.COMMUNITY); + Article actualArticle = articleRepository.findById(article.getId()).orElseThrow(); + + StudyRoom expectStudyRoom = new StudyRoom(study.getId(), owner.getId(), Set.of()); + CommunityArticle expectArticle = new CommunityArticle(article.getId(), "제목 수정", "내용 수정", owner.getId(), + expectStudyRoom); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(actualArticle).isEqualTo(expectArticle); diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/ArticleTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/ArticleTest.java new file mode 100644 index 000000000..54500f51d --- /dev/null +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/ArticleTest.java @@ -0,0 +1,90 @@ +package com.woowacourse.moamoa.studyroom.domain; + +import static com.woowacourse.moamoa.studyroom.domain.ArticleType.COMMUNITY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.woowacourse.moamoa.member.domain.Member; +import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class ArticleTest { + + @DisplayName("스터디에 참여한 참가자만 게시글을 작성할 수 있다.") + @Test + void writeCommunityArticleByParticipant() { + long studyId = 1L; + Member owner = createMember(1L); + Member another = createMember(2L); + StudyRoom studyRoom = createPermittedAccessors(studyId, owner); + Accessor accessor = new Accessor(another.getId(), 1L); + + assertThatThrownBy(() -> studyRoom.write(accessor, "제목", "내용", COMMUNITY)) + .isInstanceOf(NotParticipatedMemberException.class); + } + + @DisplayName("스터디 참여자는 게시글을 조회할 수 있다.") + @ParameterizedTest + @CsvSource({"1,true", "2,true", "3,false"}) + void getArticle(Long viewerId, boolean expected) { + long studyId = 1L; + Member owner = createMember(1L); + Member participant = createMember(2L); + StudyRoom studyRoom = createPermittedAccessors(studyId, owner, participant); + Accessor accessor = new Accessor(owner.getId(), studyId); + Article article = studyRoom.write(accessor, "제목", "내용", COMMUNITY); + + assertThat(article.isViewableBy(new Accessor(viewerId, studyId))).isEqualTo(expected); + } + + @DisplayName("스터디에 속해 있는 게시글이 맞을 경우 조회할 수 있다.") + @ParameterizedTest + @CsvSource({"1,1,true", "1,2,false"}) + void deleteArticle(Long studyId, Long wantToViewStudyId, boolean expected) { + Member member = createMember(1L); + StudyRoom studyRoom = createPermittedAccessors(studyId, member); + Accessor accessor = new Accessor(member.getId(), studyId); + Article article = studyRoom.write(accessor, "제목", "내용", COMMUNITY); + + assertThat(article.isViewableBy(new Accessor(member.getId(), wantToViewStudyId))).isEqualTo(expected); + } + + @DisplayName("스터디에 참여했고, 작성자인 경우 스터디 게시글을 수정,삭제할 수 있다.") + @ParameterizedTest + @CsvSource({"1,true", "2,false", "3,false"}) + void updateArticle(Long editorId, boolean expected) { + Member owner = createMember(1L); + Member participant = createMember(2L); + StudyRoom studyRoom = createPermittedAccessors(1L, owner, participant); + Accessor accessor = new Accessor(owner.getId(), 1L); + Article article = studyRoom.write(accessor, "제목", "내용", COMMUNITY); + + assertThat(article.isEditableBy(new Accessor(editorId, 1L))).isEqualTo(expected); + } + + @DisplayName("스터디에 속해 있지 않은 게시글인 경우 수정,삭제할 수 없다.") + @Test + void editArticleByInvalidStudyId() { + Member member = createMember(1L); + StudyRoom studyRoom = createPermittedAccessors(1L, member); + Accessor accessor = new Accessor(member.getId(), 1L); + Article article = studyRoom.write(accessor, "제목", "내용", COMMUNITY); + + assertThat(article.isViewableBy(new Accessor(member.getId(), 2L))).isFalse(); + } + + private StudyRoom createPermittedAccessors(long studyId, Member owner, Member... participant) { + final Set participants = Stream.of(participant).map(Member::getId).collect(Collectors.toSet()); + return new StudyRoom(studyId, owner.getId(), participants); + } + + private Member createMember(final long id) { + return new Member(id, id, "username" + id, "image", "profile"); + } +} diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java deleted file mode 100644 index 6ce71a2aa..000000000 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticleTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.woowacourse.moamoa.studyroom.domain; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.woowacourse.moamoa.member.domain.Member; -import com.woowacourse.moamoa.member.service.exception.NotParticipatedMemberException; -import com.woowacourse.moamoa.study.domain.AttachedTags; -import com.woowacourse.moamoa.study.domain.Content; -import com.woowacourse.moamoa.study.domain.Participants; -import com.woowacourse.moamoa.study.domain.RecruitPlanner; -import com.woowacourse.moamoa.study.domain.RecruitStatus; -import com.woowacourse.moamoa.study.domain.Study; -import com.woowacourse.moamoa.study.domain.StudyPlanner; -import com.woowacourse.moamoa.study.domain.StudyStatus; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -class CommunityArticleTest { - - @DisplayName("스터디에 참여한 참가자만 게시글을 작성할 수 있다.") - @Test - void writeCommunityArticleByParticipant() { - final Member owner = createMember(1L); - final Member another = createMember(2L); - final Study study = createStudy(1L, owner); - - assertThatThrownBy(() -> Article.write(another.getId(), study, "제목", "내용", ArticleType.COMMUNITY)) - .isInstanceOf(NotParticipatedMemberException.class); - } - - @DisplayName("스터디 참여자는 게시글을 조회할 수 있다.") - @ParameterizedTest - @CsvSource({"1,true", "2,true", "3,false"}) - void getArticle(Long viewerId, boolean expected) { - final Member owner = createMember(1L); - final Member participant = createMember(2L); - final Study study = createStudy(1L, owner); - study.participate(participant.getId()); - - final Article communityArticle = Article.write(owner.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - - assertThat(communityArticle.isViewableBy(new Accessor(viewerId, study.getId()))).isEqualTo(expected); - } - - @DisplayName("스터디에 속해 있는 게시글이 맞을 경우 조회할 수 있다.") - @ParameterizedTest - @CsvSource({"1,1,true", "1,2,false"}) - void deleteArticle(Long studyId, Long wantToViewStudyId, boolean expected) { - final Member member = createMember(1L); - final Study study = createStudy(studyId, member); - final Article communityArticle = Article.write(member.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - - assertThat(communityArticle.isViewableBy(new Accessor(member.getId(), wantToViewStudyId))).isEqualTo(expected); - } - - @DisplayName("스터디에 참여했고, 작성자인 경우 스터디 게시글을 수정,삭제할 수 있다.") - @ParameterizedTest - @CsvSource({"1,true", "2,false", "3,false"}) - void updateArticle(Long editorId, boolean expected) { - final Member owner = createMember(1L); - final Member participant = createMember(2L); - final Study study = createStudy(1L, owner); - study.participate(participant.getId()); - final Article communityArticle = Article.write(owner.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - - assertThat(communityArticle.isEditableBy(new Accessor(editorId, study.getId()))).isEqualTo(expected); - } - - @DisplayName("스터디에 속해 있지 않은 게시글인 경우 수정,삭제할 수 없다.") - @Test - void editArticleByInvalidStudyId() { - final Member member = createMember(1L); - final Study study = createStudy(1L, member); - final Article communityArticle = Article.write(member.getId(), study, "제목", "내용", ArticleType.COMMUNITY); - - assertThat(communityArticle.isViewableBy(new Accessor(member.getId(), 2L))).isFalse(); - } - - private Study createStudy(final long id, final Member owner) { - return new Study(id, - new Content("제목", "한 줄 소개", "http://image", "설명"), - Participants.createBy(owner.getId()), - new RecruitPlanner(10, RecruitStatus.RECRUITMENT_START, null), - new StudyPlanner(LocalDate.now(), null, StudyStatus.IN_PROGRESS), - new AttachedTags(List.of()), - LocalDateTime.now() - ); - } - - private Member createMember(final long id) { - return new Member(id, id, "username" + id, "image", "profile"); - } -} From 72650c5dab56cbaab85617cfa33cb03de64b78ad Mon Sep 17 00:00:00 2001 From: Donggyu Date: Tue, 16 Aug 2022 17:03:37 +0900 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/utils/tw.ts | 270 ++++++++++++++++++++++++++++++++++++ frontend/tailwind.config.js | 29 ++++ 2 files changed, 299 insertions(+) create mode 100644 frontend/src/utils/tw.ts create mode 100644 frontend/tailwind.config.js diff --git a/frontend/src/utils/tw.ts b/frontend/src/utils/tw.ts new file mode 100644 index 000000000..2bcc1a374 --- /dev/null +++ b/frontend/src/utils/tw.ts @@ -0,0 +1,270 @@ +// quick style sheet +import { css } from '@emotion/react'; + +const arr0_to_100 = [...Array(101).keys()]; +const arr0_to_300 = [...Array(301).keys()]; + +const layout = { + block: 'display: block', + 'inline-block': 'display: inline-block', + inline: 'display: inline', + flex: 'display: flex', + 'inline-flex': 'display: inline-flex', + table: 'display: table', + 'inline-table': 'display: inline-table', + 'table-caption': 'display: table-caption', + 'table-cell': 'display: table-cell', + 'table-column': 'display: table-column', + 'table-column-group': 'display: table-column-group', + 'table-footer-group': 'display: table-footer-group', + 'table-header-group': 'display: table-header-group', + 'table-row-group': 'display: table-row-group', + 'table-row': 'display: table-row', + 'flow-root': 'display: flow-root', + grid: 'display: grid', + 'inline-grid': 'display: inline-grid', + contents: 'display: contents', + 'list-item': 'display: list-item', + hidden: 'display: none', +}; + +const flex = { + 'flex-1': 'flex: 1 1 0%', + 'flex-auto': 'flex: 1 1 auto', + 'flex-initial': 'flex: 0 1 auto', + 'flex-none': 'flex: none', +}; + +const justifyContent = { + 'justify-start': 'justify-content: flex-start', + 'justify-end': 'justify-content: flex-end', + 'justify-center': 'justify-content: center', + 'justify-between': 'justify-content: space-between', + 'justify-around': 'justify-content: space-around', + 'justify-evenly': 'justify-content: space-evenly', +}; + +const alignItems = { + 'items-start': 'align-items: flex-start', + 'items-end': 'align-items: flex-end', + 'items-center': 'align-items: center', + 'items-baseline': 'align-items: baseline', + 'items-stretch': 'align-items: stretch', +}; + +const alignSelf = { + 'self-auto': 'align-self: auto', + 'self-start': 'align-self: flex-start', + 'self-end': 'align-self: flex-end', + 'self-center': 'align-self: center', + 'self-stretch': 'align-self: stretch', + 'self-baseline': 'align-self: baseline', +}; + +const margin = arr0_to_100.reduce((acc, cur) => { + acc[`mt-${cur}`] = `margin-top: ${cur}px`; + acc[`mr-${cur}`] = `margin-right: ${cur}px`; + acc[`mb-${cur}`] = `margin-bottom: ${cur}px`; + acc[`ml-${cur}`] = `margin-left: ${cur}px`; + return acc; +}, {} as Record); + +const padding = arr0_to_100.reduce((acc, cur) => { + acc[`p-${cur}`] = `padding-top: ${cur}px; padding-right: ${cur}px; padding-bottom: ${cur}px; padding-left: ${cur}px`; + acc[`py-${cur}`] = `padding-top: ${cur}px; padding-bottom: ${cur}px`; + acc[`px-${cur}`] = `padding-left: ${cur}px; padding-right: ${cur}px`; + + acc[`pt-${cur}`] = `padding-top: ${cur}px`; + acc[`pr-${cur}`] = `padding-right: ${cur}px`; + acc[`pb-${cur}`] = `padding-bottom: ${cur}px`; + acc[`pl-${cur}`] = `padding-left: ${cur}px`; + return acc; +}, {} as Record); + +const widthPx = arr0_to_300.reduce((acc, cur) => { + acc[`w-${cur}`] = `width: ${cur}px`; + acc[`max-w-${cur}`] = `max-width: ${cur}px`; + return acc; +}, {} as Record); + +const width = { + 'w-full': 'width: 100%', +}; + +const heightPx = arr0_to_300.reduce((acc, cur) => { + acc[`h-${cur}px`] = `height: ${cur}px`; + acc[`max-h-${cur}px`] = `max-height: ${cur}px`; + return acc; +}, {} as Record); + +const height = { + 'h-full': 'height: 100%', +}; + +const position = { + static: 'position: static', + fixed: 'position: fixed', + absolute: 'position: absolute', + relative: 'position: relative', + sticky: 'position: sticky', +}; + +const trbl = arr0_to_100.reduce((acc, cur) => { + acc[`top-${cur}`] = `top: ${cur}px`; + acc[`right-${cur}`] = `right: ${cur}px`; + acc[`bottom-${cur}`] = `bottom: ${cur}px`; + acc[`left-${cur}`] = `left: ${cur}px`; + return acc; +}, {} as Record); + +const zIndex = arr0_to_100.reduce((acc, cur) => { + acc[`z-${cur}`] = `z-index: ${cur}`; + return acc; +}, {} as Record); + +const overflow = { + 'overflow-auto': 'overflow: auto', + 'overflow-hidden': 'overflow: hidden', + 'overflow-clip': 'overflow: clip', + 'overflow-visible': 'overflow: visible', + 'overflow-scroll': 'overflow: scroll', + 'overflow-x-auto': 'overflow-x: auto', + 'overflow-y-auto': 'overflow-y: auto', + 'overflow-x-hidden': 'overflow-x: hidden', + 'overflow-y-hidden': 'overflow-y: hidden', + 'overflow-x-clip': 'overflow-x: clip', + 'overflow-y-clip': 'overflow-y: clip', + 'overflow-x-visible': 'overflow-x: visible', + 'overflow-y-visible': 'overflow-y: visible', + 'overflow-x-scroll': 'overflow-x: scroll', + 'overflow-y-scroll': 'overflow-y: scroll', +}; + +const textAlign = { + 'text-left': 'text-align: left', + 'text-center': 'text-align: center', + 'text-right': 'text-align: right', + 'text-justify': 'text-align: justify', + 'text-start': 'text-align: start', + 'text-end': 'text-align: end', +}; + +const borderRadius = arr0_to_100.reduce((acc, cur) => { + acc[`rounded-${cur}`] = `border-radius: ${cur}px`; + acc[`rounded-t-${cur}`] = `border-top-left-radius: ${cur}px; border-top-right-radius: ${cur}px`; + acc[`rounded-r-${cur}`] = `border-top-right-radius: ${cur}px; border-bottom-right-radius: ${cur}px`; + acc[`rounded-b-${cur}`] = `border-bottom-right-radius: ${cur}px; border-bottom-left-radius: ${cur}px`; + acc[`rounded-l-${cur}`] = `border-top-left-radius: ${cur}px; border-bottom-left-radius: ${cur}px`; + + return acc; +}, {} as Record); + +const fontSize = arr0_to_100.reduce((acc, cur) => { + acc[`text-${cur}`] = `font-size: ${cur}px`; + return acc; +}, {} as Record); + +const totalStyles = { + ...layout, + ...flex, + ...justifyContent, + ...alignItems, + ...alignSelf, + ...margin, + ...padding, + ...widthPx, + ...width, + ...heightPx, + ...height, + ...position, + ...trbl, + ...zIndex, + ...overflow, + ...textAlign, + ...borderRadius, + ...fontSize, +}; + +const cssPropertyForArbitararyValue = { + // margin + mt: ['margin-top'], + mr: ['margin-right'], + mb: ['margin-bottom'], + ml: ['margin-left'], + m: ['margin-top', 'margin-right', 'margin-bottom', 'margin-left'], + my: ['margin-top', 'margin-bottom'], + mx: ['margin-left', 'margin-right'], + + // padding + pt: ['padding-top'], + pr: ['padding-right'], + pb: ['padding-bottom'], + pl: ['padding-left'], + p: ['padding-top', 'padding-right', 'padding-bottom', 'padding-left'], + py: ['padding-top', 'padding-bottom'], + px: ['padding-left', 'padding-right'], + + // size + h: ['height'], + w: ['width'], + 'max-w': ['max-width'], + 'min-w': ['min-width'], + + // border + rounded: ['border-radius'], + + // typo + text: ['font-size'], +}; + +type styleKey = keyof typeof totalStyles; +type cssShortPropertyKey = keyof typeof cssPropertyForArbitararyValue; + +const getArbitararyValue = (str: string) => { + return str.substring(str.indexOf('[') + 1, str.indexOf(']')); +}; + +// TODO: Test 코드 만들자 +const combine = (template: TemplateStringsArray, args: Array): string => { + const result = []; + for (let i = 0; i < template.length - 1; i += 1) { + result.push(template[i]); + result.push(args[i]); + } + result.push(template[template.length - 1]); + return result.join(''); +}; + +// TODO: Test 코드 만들다 +const tw = (template: TemplateStringsArray, ...args: Array) => { + let templateStr = template[0]; + if (template.length > 1) templateStr = combine(template, args); + + const styles = templateStr.split(' '); + const styleText = styles + .map(s => { + const arbitararyValue = getArbitararyValue(s); + + if (arbitararyValue) { + // py-[12px]에서 ['py-', '[12px]']로 짜르고 마지막 요소를 빼낸다 + const shortCssProperty = s.split('-').slice(0, -1)[0]; + const fullCssProperties = cssPropertyForArbitararyValue[shortCssProperty as cssShortPropertyKey]; + const cssTexts = fullCssProperties.map(fullCssProp => { + return `${fullCssProp}: ${arbitararyValue}`; + }); + return cssTexts.join(';'); + } + if (!(s in totalStyles)) { + throw new Error('올바른 스타일을 입력해 주세요'); + } + return totalStyles[s as styleKey]; + }) + .join(';'); + + // 마지막 ;도 중요하다! + return css` + ${styleText}; + `; +}; + +export default tw; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js new file mode 100644 index 000000000..282e204f5 --- /dev/null +++ b/frontend/tailwind.config.js @@ -0,0 +1,29 @@ +/** @type {import('tailwindcss').Config} */ + +const arr0_to_100 = [...Array(101).keys()]; +const px0_50 = { ...Array.from(Array(51)).map((_, i) => `${i}px`) }; +const px0_100 = { ...Array.from(Array(101)).map((_, i) => `${i}px`) }; +const px0_500 = { ...Array.from(Array(501)).map((_, i) => `${i}px`) }; + +module.exports = { + content: ['src/components/*.tsx', 'src/pages/*.tsx'], + theme: { + extend: { + borderWidth: px0_50, + fontSize: px0_100, + lineHeight: px0_100, + width: px0_500, + maxWidth: px0_500, + minWidth: px0_500, + maxHeight: px0_500, + minHeight: px0_500, + spacing: px0_100, + zIndex: arr0_to_100, + top: arr0_to_100, + right: arr0_to_100, + bottom: arr0_to_100, + left: arr0_to_100, + }, + }, + plugins: [], +}; From fb5f2a25e1658727ca1fe924050c120768356fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=98=81?= Date: Wed, 17 Aug 2022 20:01:40 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moamoa/studyroom/domain/Article.java | 22 ++++++------------- .../studyroom/domain/CommunityArticle.java | 10 +++++++++ .../studyroom/domain/NoticeArticle.java | 12 +++++++++- .../moamoa/studyroom/query/ArticleDao.java | 4 ++-- .../acceptance/steps/StudyRelatedSteps.java | 8 +++---- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java index a31c5bba9..7a2030836 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/Article.java @@ -36,29 +36,21 @@ public Article(final Long id, final Long authorId, StudyRoom studyRoom) { this.studyRoom = studyRoom; } - public boolean isViewableBy(final Accessor accessor) { + protected final boolean isPermittedAccessor(final Accessor accessor) { return studyRoom.isPermittedAccessor(accessor); } - public boolean isEditableBy(final Accessor accessor) { - return studyRoom.isPermittedAccessor(accessor) && isAuthor(accessor); + protected final boolean isAuthor(final Accessor accessor) { + return this.authorId.equals(accessor.getMemberId()); } - private boolean isAuthor(final Accessor accessor) { - return this.authorId.equals(accessor.getMemberId()); + protected final boolean isOwner(final Accessor accessor) { + return studyRoom.isOwner(accessor); } public abstract void update(Accessor accessor, String title, String content); - public Article write(final Accessor accessor, final StudyRoom studyRoom, final String title, final String content, final ArticleType type) { - if (type == ArticleType.COMMUNITY && studyRoom.isPermittedAccessor(accessor)) { - return new CommunityArticle(title, content, accessor.getMemberId(), studyRoom); - } + public abstract boolean isEditableBy(final Accessor accessor); - if (type == ArticleType.NOTICE && studyRoom.isOwner(accessor)) { - return new NoticeArticle(title, content, accessor.getMemberId(), studyRoom); - } - - throw new NotParticipatedMemberException(); - } + public abstract boolean isViewableBy(final Accessor accessor); } diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java index e994e3df5..c44a6f1fa 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/CommunityArticle.java @@ -31,6 +31,16 @@ public CommunityArticle(final Long id, final String title, final String content, this.content = content; } + @Override + public boolean isViewableBy(final Accessor accessor) { + return isPermittedAccessor(accessor); + } + + @Override + public boolean isEditableBy(final Accessor accessor) { + return isPermittedAccessor(accessor) && isAuthor(accessor); + } + @Override public void update(final Accessor accessor, final String title, final String content) { if (!isEditableBy(accessor)) { diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java index 2949f69e5..2f70da4aa 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/domain/NoticeArticle.java @@ -32,7 +32,17 @@ public NoticeArticle(final Long id, final String title, final String content, fi } @Override - public void update(final Accessor accessor, final String title, final String content) { + public final boolean isViewableBy(final Accessor accessor) { + return isPermittedAccessor(accessor); + } + + @Override + public final boolean isEditableBy(final Accessor accessor) { + return isOwner(accessor); + } + + @Override + public final void update(final Accessor accessor, final String title, final String content) { if (!isEditableBy(accessor)) { throw new IllegalArgumentException(); } diff --git a/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java b/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java index 1ca24f1a1..665cbf4aa 100644 --- a/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java +++ b/backend/src/main/java/com/woowacourse/moamoa/studyroom/query/ArticleDao.java @@ -39,14 +39,14 @@ public ArticleDao(final NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; } - public Optional getById(final Long communityId, ArticleType type) { + public Optional getById(final Long articleId, ArticleType type) { final String sql = "SELECT {}.id as article_id, {}.title as article_title, {}.content as article_content, " + "{}.created_date as article_created_date, {}.last_modified_date as article_last_modified_date, " + "member.github_id, member.username, member.image_url, member.profile_url " + "FROM {} JOIN member ON {}.author_id = member.id " + "WHERE {}.id = :{}Id"; - final Map params = Map.of(nameOf(type) + "Id", communityId); + final Map params = Map.of(nameOf(type) + "Id", articleId); return namedParameterJdbcTemplate.query(sql.replaceAll("\\{\\}", nameOf(type)), params, ROW_MAPPER).stream().findAny(); } diff --git a/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java b/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java index 9456cc359..540a8c3a6 100644 --- a/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java +++ b/backend/src/test/java/com/woowacourse/acceptance/steps/StudyRelatedSteps.java @@ -68,7 +68,7 @@ public class StudyRelatedSteps extends Steps { } } - public long 공지사항을_작성한다(final String title, final String content) { + public Long 공지사항을_작성한다(final String title, final String content) { try { final String location = RestAssured.given().log().all() .header(org.apache.http.HttpHeaders.AUTHORIZATION, token) @@ -83,11 +83,11 @@ public class StudyRelatedSteps extends Steps { return Long.parseLong(location.replaceAll("/api/studies/" + studyId + "/notice/articles/", "")); } catch (Exception e) { Assertions.fail("공지사항 작성 실패"); - return -1; + return null; } } - public long 게시글을_작성한다(final String title, final String content) { + public Long 게시글을_작성한다(final String title, final String content) { try { final String location = RestAssured.given().log().all() .header(org.apache.http.HttpHeaders.AUTHORIZATION, token) @@ -102,7 +102,7 @@ public class StudyRelatedSteps extends Steps { return Long.parseLong(location.replaceAll("/api/studies/" + studyId + "/community/articles/", "")); } catch (Exception e) { Assertions.fail("게시글 작성 실패"); - return -1; + return null; } } } From 80d1cff3b729f03de2e35165ece35658c2529b1b Mon Sep 17 00:00:00 2001 From: Donggyu Date: Wed, 17 Aug 2022 21:06:49 +0900 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moamoa/studyroom/controller/ArticleControllerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java index 7c0ddad92..a1777fbac 100644 --- a/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java +++ b/backend/src/test/java/com/woowacourse/moamoa/studyroom/controller/ArticleControllerTest.java @@ -13,13 +13,13 @@ import com.woowacourse.moamoa.study.domain.repository.StudyRepository; import com.woowacourse.moamoa.study.service.StudyService; import com.woowacourse.moamoa.study.service.exception.StudyNotFoundException; -import com.woowacourse.moamoa.study.service.request.CreatingStudyRequestBuilder; +import com.woowacourse.moamoa.study.service.request.StudyRequestBuilder; import com.woowacourse.moamoa.studyroom.domain.Article; import com.woowacourse.moamoa.studyroom.domain.CommunityArticle; import com.woowacourse.moamoa.studyroom.domain.NoticeArticle; import com.woowacourse.moamoa.studyroom.domain.StudyRoom; -import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; import com.woowacourse.moamoa.studyroom.domain.repository.article.ArticleRepositoryFactory; +import com.woowacourse.moamoa.studyroom.domain.repository.studyroom.StudyRoomRepository; import com.woowacourse.moamoa.studyroom.query.ArticleDao; import com.woowacourse.moamoa.studyroom.service.ArticleService; import com.woowacourse.moamoa.studyroom.service.request.ArticleRequest; @@ -35,7 +35,7 @@ @RepositoryTest public class ArticleControllerTest { - CreatingStudyRequestBuilder javaStudyRequest = new CreatingStudyRequestBuilder() + StudyRequestBuilder javaStudyRequest = new StudyRequestBuilder() .title("java 스터디").excerpt("자바 설명").thumbnail("java image").description("자바 소개"); @Autowired