From 8a95686439c63f9d2a5dbc2dbe01db3707f66cbd Mon Sep 17 00:00:00 2001 From: amaran-th Date: Sat, 18 Nov 2023 22:41:04 +0900 Subject: [PATCH 01/20] =?UTF-8?q?refactor:=20admin=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - admin 패키지를 분리 - admin api의 uri 수정 #156 --- .../java/com/emmsale/ActivityApiTest.java | 49 ++++++++++--------- .../java/com/emmsale/EventApiTest.java | 19 +++---- .../java/com/emmsale/MockMvcTestHelper.java | 8 +-- .../java/com/emmsale/ReportApiTest.java | 5 +- .../java/com/emmsale/TagApiTest.java | 5 +- .../com/emmsale/activity/api/ActivityApi.java | 14 ------ .../admin/activity/api/AdminActivityApi.java | 28 +++++++++++ .../application/ActivityCommandService.java | 3 +- .../admin/event/api/AdminEventApi.java | 48 ++++++++++++++++++ .../application/EventCommandService.java | 2 +- .../admin/report/api/AdminReportApi.java | 22 +++++++++ .../application/ReportQueryService.java | 2 +- .../emmsale/admin/tag/api/AdminTagApi.java | 25 ++++++++++ .../tag/application/TagCommandService.java | 2 +- .../java/com/emmsale/event/api/EventApi.java | 33 ------------- .../com/emmsale/report/api/ReportApi.java | 10 ---- .../main/java/com/emmsale/tag/api/TagApi.java | 11 ----- .../ActivityCommandServiceTest.java | 18 +++---- .../application/EventCommandServiceTest.java | 41 +--------------- ...EventServiceEventIntegrationTestQuery.java | 2 +- .../application/ReportQueryServiceTest.java | 3 +- .../application/TagCommandServiceTest.java | 2 +- 22 files changed, 187 insertions(+), 165 deletions(-) create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java rename backend/emm-sale/src/main/java/com/emmsale/{ => admin}/activity/application/ActivityCommandService.java (95%) create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java rename backend/emm-sale/src/main/java/com/emmsale/{ => admin}/event/application/EventCommandService.java (98%) create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java rename backend/emm-sale/src/main/java/com/emmsale/{ => admin}/report/application/ReportQueryService.java (92%) create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java rename backend/emm-sale/src/main/java/com/emmsale/{ => admin}/tag/application/TagCommandService.java (95%) rename backend/emm-sale/src/test/java/com/emmsale/{ => admin}/activity/application/ActivityCommandServiceTest.java (82%) rename backend/emm-sale/src/test/java/com/emmsale/{ => admin}/event/application/EventCommandServiceTest.java (85%) rename backend/emm-sale/src/test/java/com/emmsale/{ => admin}/event/application/EventServiceEventIntegrationTestQuery.java (99%) rename backend/emm-sale/src/test/java/com/emmsale/{ => admin}/report/application/ReportQueryServiceTest.java (96%) rename backend/emm-sale/src/test/java/com/emmsale/{ => admin}/tag/application/TagCommandServiceTest.java (97%) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java index 6d1d83fe4..867906f8c 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java @@ -13,6 +13,7 @@ import com.emmsale.activity.application.dto.ActivityAddRequest; import com.emmsale.activity.application.dto.ActivityResponse; import com.emmsale.activity.domain.ActivityType; +import com.emmsale.admin.activity.api.AdminActivityApi; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -27,7 +28,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -@WebMvcTest(ActivityApi.class) +@WebMvcTest({ActivityApi.class, AdminActivityApi.class}) // TODO: 2023/11/18 Admin API Test 분리하기 class ActivityApiTest extends MockMvcTestHelper { @Test @@ -35,26 +36,26 @@ class ActivityApiTest extends MockMvcTestHelper { void findAll() throws Exception { // given final ResponseFieldsSnippet responseFields = PayloadDocumentation.responseFields( - fieldWithPath("[].id").type(JsonFieldType.NUMBER).description("activity id"), - fieldWithPath("[].activityType").type(JsonFieldType.STRING).description("activity 분류"), - fieldWithPath("[].name").type(JsonFieldType.STRING).description("activity 이름") + fieldWithPath("[].id").type(JsonFieldType.NUMBER).description("activity id"), + fieldWithPath("[].activityType").type(JsonFieldType.STRING).description("activity 분류"), + fieldWithPath("[].name").type(JsonFieldType.STRING).description("activity 이름") ); final List expected = List.of( - new ActivityResponse(1L, "동아리", "YAPP"), - new ActivityResponse(2L, "동아리", "DND"), - new ActivityResponse(3L, "동아리", "nexters"), - new ActivityResponse(4L, "컨퍼런스", "인프콘"), - new ActivityResponse(5L, "교육", "우아한테크코스"), - new ActivityResponse(6L, "직무", "Backend") + new ActivityResponse(1L, "동아리", "YAPP"), + new ActivityResponse(2L, "동아리", "DND"), + new ActivityResponse(3L, "동아리", "nexters"), + new ActivityResponse(4L, "컨퍼런스", "인프콘"), + new ActivityResponse(5L, "교육", "우아한테크코스"), + new ActivityResponse(6L, "직무", "Backend") ); Mockito.when(activityQueryService.findAll()).thenReturn(expected); // when & then mockMvc.perform(MockMvcRequestBuilders.get("/activities")) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andDo(MockMvcRestDocumentation.document("find-all-activities", responseFields)); + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcRestDocumentation.document("find-all-activities", responseFields)); } @Test @@ -62,29 +63,29 @@ void findAll() throws Exception { void addTag() throws Exception { //given final RequestFieldsSnippet requestFields = requestFields( - fieldWithPath("activityType").type(JsonFieldType.STRING).description("활동 유형"), - fieldWithPath("name").type(JsonFieldType.STRING).description("활동 이름") + fieldWithPath("activityType").type(JsonFieldType.STRING).description("활동 유형"), + fieldWithPath("name").type(JsonFieldType.STRING).description("활동 이름") ); final ActivityAddRequest request = new ActivityAddRequest(ActivityType.CLUB, "DND"); final ActivityResponse response = new ActivityResponse(3L, - ActivityType.CLUB.getValue(), - "DND" + ActivityType.CLUB.getValue(), + "DND" ); when(activityCommandService.addActivity(any(ActivityAddRequest.class))).thenReturn(response); final ResponseFieldsSnippet responseFields = responseFields( - fieldWithPath("id").type(JsonFieldType.NUMBER).description("활동 식별자"), - fieldWithPath("activityType").type(JsonFieldType.STRING).description("활동 종류"), - fieldWithPath("name").type(JsonFieldType.STRING).description("활동 이름") + fieldWithPath("id").type(JsonFieldType.NUMBER).description("활동 식별자"), + fieldWithPath("activityType").type(JsonFieldType.STRING).description("활동 종류"), + fieldWithPath("name").type(JsonFieldType.STRING).description("활동 이름") ); //when & then - mockMvc.perform(post("/activities") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) - .andExpect(status().isCreated()) - .andDo(document("add-activity", requestFields, responseFields)); + mockMvc.perform(post("/admin/activities") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isCreated()) + .andDo(document("add-activity", requestFields, responseFields)); } } diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java index ef69d49b0..1dfd3ea7a 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java @@ -11,6 +11,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.emmsale.admin.event.api.AdminEventApi; import com.emmsale.event.EventFixture; import com.emmsale.event.api.EventApi; import com.emmsale.event.application.dto.EventDetailRequest; @@ -52,7 +53,7 @@ import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; -@WebMvcTest(EventApi.class) +@WebMvcTest({EventApi.class, AdminEventApi.class}) class EventApiTest extends MockMvcTestHelper { private static final ResponseFieldsSnippet EVENT_DETAIL_RESPONSE_FILED = PayloadDocumentation.responseFields( @@ -259,7 +260,7 @@ void updateEventTest() throws Exception { //when final MockMultipartHttpServletRequestBuilder builder = multipart(HttpMethod.PUT, - "/events/" + eventId) + "/admin/events/" + eventId) .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( @@ -285,7 +286,7 @@ void deleteEventTest() throws Exception { Mockito.doNothing().when(eventCommandService).deleteEvent(eventId); //when final ResultActions result = mockMvc.perform( - delete("/events/" + eventId)); + delete("/admin/events/" + eventId)); //then result.andExpect(status().isNoContent()) @@ -360,7 +361,7 @@ void addEventTest() throws Exception { ); //when - final MockMultipartHttpServletRequestBuilder builder = multipart("/events") + final MockMultipartHttpServletRequestBuilder builder = multipart("/admin/events") .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( @@ -407,7 +408,7 @@ void addEventWithEmptyNameTest(final String eventName) throws Exception { event.getPaymentType(), event.getOrganization()); final String contents = objectMapper.writeValueAsString(request); //when & then - mockMvc.perform(multipart("/events") + mockMvc.perform(multipart("/admin/events") .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( @@ -448,7 +449,7 @@ void addEventWithEmptyLocationTest(final String eventLocation) throws Exception event.getPaymentType(), event.getOrganization()); final String contents = objectMapper.writeValueAsString(request); //when & then - mockMvc.perform(multipart("/events") + mockMvc.perform(multipart("/admin/events") .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( @@ -490,7 +491,7 @@ void addEventWithInvalidInformationUrlTest(final String informationUrl) throws E event.getPaymentType(), event.getOrganization()); final String contents = objectMapper.writeValueAsString(request); //when & then - mockMvc.perform(multipart("/events") + mockMvc.perform(multipart("/admin/events") .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( @@ -538,7 +539,7 @@ void addEventWithUnformattedStartDateTimeTest(final String startDateTime) final String contents = objectMapper.writeValueAsString(request); //when & then - mockMvc.perform(multipart("/events") + mockMvc.perform(multipart("/admin/events") .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( @@ -585,7 +586,7 @@ void addEventWithUnformattedEndDateTimeTest(final String endDateTime) throws Exc final String contents = objectMapper.writeValueAsString(request); //when & then - mockMvc.perform(multipart("/events") + mockMvc.perform(multipart("/admin/events") .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java b/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java index 350bfbf05..a5ee07bab 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java @@ -3,13 +3,15 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import com.emmsale.activity.application.ActivityCommandService; import com.emmsale.activity.application.ActivityQueryService; +import com.emmsale.admin.activity.application.ActivityCommandService; +import com.emmsale.admin.event.application.EventCommandService; +import com.emmsale.admin.report.application.ReportQueryService; +import com.emmsale.admin.tag.application.TagCommandService; import com.emmsale.block.application.BlockCommandService; import com.emmsale.block.application.BlockQueryService; import com.emmsale.comment.application.CommentCommandService; import com.emmsale.comment.application.CommentQueryService; -import com.emmsale.event.application.EventCommandService; import com.emmsale.event.application.EventQueryService; import com.emmsale.event.application.RecruitmentPostCommandService; import com.emmsale.event.application.RecruitmentPostQueryService; @@ -27,11 +29,9 @@ import com.emmsale.notification.application.NotificationCommandService; import com.emmsale.notification.application.NotificationQueryService; import com.emmsale.report.application.ReportCommandService; -import com.emmsale.report.application.ReportQueryService; import com.emmsale.resolver.MemberArgumentResolver; import com.emmsale.scrap.application.ScrapCommandService; import com.emmsale.scrap.application.ScrapQueryService; -import com.emmsale.tag.application.TagCommandService; import com.emmsale.tag.application.TagQueryService; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java index 580fcbf05..ef572149a 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java @@ -10,6 +10,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.emmsale.admin.report.api.AdminReportApi; import com.emmsale.report.api.ReportApi; import com.emmsale.report.application.dto.ReportCreateRequest; import com.emmsale.report.application.dto.ReportCreateResponse; @@ -25,7 +26,7 @@ import org.springframework.restdocs.payload.RequestFieldsSnippet; import org.springframework.restdocs.payload.ResponseFieldsSnippet; -@WebMvcTest(ReportApi.class) +@WebMvcTest({ReportApi.class, AdminReportApi.class}) class ReportApiTest extends MockMvcTestHelper { @Test @@ -100,7 +101,7 @@ void findReports() throws Exception { when(reportQueryService.findReports()).thenReturn(reportFindResponse); // when & then - mockMvc.perform(get("/reports")) + mockMvc.perform(get("/admin/reports")) .andExpect(status().isOk()) .andDo(document("find-reports", responseFields)); } diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java index fd15419a4..03d92eecc 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java @@ -10,6 +10,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.emmsale.admin.tag.api.AdminTagApi; import com.emmsale.tag.api.TagApi; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; @@ -22,7 +23,7 @@ import org.springframework.restdocs.payload.RequestFieldsSnippet; import org.springframework.restdocs.payload.ResponseFieldsSnippet; -@WebMvcTest(TagApi.class) +@WebMvcTest({TagApi.class, AdminTagApi.class}) class TagApiTest extends MockMvcTestHelper { @Test @@ -66,7 +67,7 @@ void addTag() throws Exception { ); //when & then - mockMvc.perform(post("/tags") + mockMvc.perform(post("/admin/tags") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isCreated()) diff --git a/backend/emm-sale/src/main/java/com/emmsale/activity/api/ActivityApi.java b/backend/emm-sale/src/main/java/com/emmsale/activity/api/ActivityApi.java index ed2e74e79..d8a600abc 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/activity/api/ActivityApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/activity/api/ActivityApi.java @@ -1,16 +1,11 @@ package com.emmsale.activity.api; -import com.emmsale.activity.application.ActivityCommandService; import com.emmsale.activity.application.ActivityQueryService; -import com.emmsale.activity.application.dto.ActivityAddRequest; import com.emmsale.activity.application.dto.ActivityResponse; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -20,18 +15,9 @@ public class ActivityApi { private final ActivityQueryService activityQueryService; - private final ActivityCommandService activityCommandService; @GetMapping public ResponseEntity> findAll() { return ResponseEntity.ok(activityQueryService.findAll()); } - - @PostMapping - public ResponseEntity create( - @RequestBody final ActivityAddRequest request - ) { - return ResponseEntity.status(HttpStatus.CREATED) - .body(activityCommandService.addActivity(request)); - } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java new file mode 100644 index 000000000..320118055 --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java @@ -0,0 +1,28 @@ +package com.emmsale.admin.activity.api; + +import com.emmsale.activity.application.dto.ActivityAddRequest; +import com.emmsale.activity.application.dto.ActivityResponse; +import com.emmsale.admin.activity.application.ActivityCommandService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/admin/activities") +@RequiredArgsConstructor +public class AdminActivityApi { + + private final ActivityCommandService activityCommandService; + + @PostMapping + public ResponseEntity create( + @RequestBody final ActivityAddRequest request + ) { + return ResponseEntity.status(HttpStatus.CREATED) + .body(activityCommandService.addActivity(request)); + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/activity/application/ActivityCommandService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java similarity index 95% rename from backend/emm-sale/src/main/java/com/emmsale/activity/application/ActivityCommandService.java rename to backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java index e5b6585fa..a60b51aaa 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/activity/application/ActivityCommandService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java @@ -1,4 +1,4 @@ -package com.emmsale.activity.application; +package com.emmsale.admin.activity.application; import com.emmsale.activity.application.dto.ActivityAddRequest; import com.emmsale.activity.application.dto.ActivityResponse; @@ -30,4 +30,3 @@ private void validateAlreadyExist(final String name) { } } } - diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java new file mode 100644 index 000000000..2c06f1166 --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java @@ -0,0 +1,48 @@ +package com.emmsale.admin.event.api; + +import com.emmsale.admin.event.application.EventCommandService; +import com.emmsale.event.application.dto.EventDetailRequest; +import com.emmsale.event.application.dto.EventResponse; +import java.util.List; +import javax.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("/admin/events") +@RequiredArgsConstructor +public class AdminEventApi { + + private final EventCommandService eventCommandService; + + @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(HttpStatus.CREATED) + public EventResponse addEvent(@RequestPart @Valid final EventDetailRequest request, + @RequestPart final List images) { + return eventCommandService.addEvent(request, images); + } + + @PutMapping(path = "/{eventId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(HttpStatus.OK) + public EventResponse updateEvent(@PathVariable final Long eventId, + @RequestPart @Valid final EventDetailRequest request, + @RequestPart final List images) { + return eventCommandService.updateEvent(eventId, request, images); + } + + @DeleteMapping("/{eventId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteEvent(@PathVariable final Long eventId) { + eventCommandService.deleteEvent(eventId); + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/application/EventCommandService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java similarity index 98% rename from backend/emm-sale/src/main/java/com/emmsale/event/application/EventCommandService.java rename to backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java index c958f360a..c6c322be4 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/application/EventCommandService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java @@ -1,4 +1,4 @@ -package com.emmsale.event.application; +package com.emmsale.admin.event.application; import static com.emmsale.event.exception.EventExceptionType.NOT_FOUND_EVENT; import static java.util.stream.Collectors.toList; diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java new file mode 100644 index 000000000..42b175317 --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java @@ -0,0 +1,22 @@ +package com.emmsale.admin.report.api; + +import com.emmsale.admin.report.application.ReportQueryService; +import com.emmsale.report.application.dto.ReportFindResponse; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/admin/reports") +@RequiredArgsConstructor +public class AdminReportApi { + + private final ReportQueryService reportQueryService; + + @GetMapping + public List findReports() { + return reportQueryService.findReports(); + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/report/application/ReportQueryService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java similarity index 92% rename from backend/emm-sale/src/main/java/com/emmsale/report/application/ReportQueryService.java rename to backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java index 6ca29076a..831070c31 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/report/application/ReportQueryService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java @@ -1,4 +1,4 @@ -package com.emmsale.report.application; +package com.emmsale.admin.report.application; import com.emmsale.report.application.dto.ReportFindResponse; import com.emmsale.report.domain.repository.ReportRepository; diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java new file mode 100644 index 000000000..5c9c12fb0 --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java @@ -0,0 +1,25 @@ +package com.emmsale.admin.tag.api; + +import com.emmsale.admin.tag.application.TagCommandService; +import com.emmsale.tag.application.dto.TagRequest; +import com.emmsale.tag.application.dto.TagResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/admin/tags") +@RequiredArgsConstructor +public class AdminTagApi { + + private final TagCommandService commandService; + + @PostMapping + public ResponseEntity create(@RequestBody final TagRequest tagRequest) { + return ResponseEntity.status(HttpStatus.CREATED).body(commandService.addTag(tagRequest)); + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/tag/application/TagCommandService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java similarity index 95% rename from backend/emm-sale/src/main/java/com/emmsale/tag/application/TagCommandService.java rename to backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java index e81fbfda0..461435587 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/tag/application/TagCommandService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java @@ -1,4 +1,4 @@ -package com.emmsale.tag.application; +package com.emmsale.admin.tag.application; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java b/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java index 7aebba943..c719bc0b7 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/api/EventApi.java @@ -1,30 +1,19 @@ package com.emmsale.event.api; -import com.emmsale.event.application.EventCommandService; import com.emmsale.event.application.EventQueryService; -import com.emmsale.event.application.dto.EventDetailRequest; import com.emmsale.event.application.dto.EventResponse; import com.emmsale.event.domain.EventStatus; import com.emmsale.event.domain.EventType; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RequestPart; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/events") @@ -32,7 +21,6 @@ public class EventApi { private final EventQueryService eventQueryService; - private final EventCommandService eventCommandService; @GetMapping("/{id}") public ResponseEntity findEventById(@PathVariable final Long id) { @@ -52,25 +40,4 @@ public ResponseEntity> findEvents( statuses, keyword)); } - - @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(HttpStatus.CREATED) - public EventResponse addEvent(@RequestPart @Valid final EventDetailRequest request, - @RequestPart final List images) { - return eventCommandService.addEvent(request, images); - } - - @PutMapping(path = "/{eventId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(HttpStatus.OK) - public EventResponse updateEvent(@PathVariable final Long eventId, - @RequestPart @Valid final EventDetailRequest request, - @RequestPart final List images) { - return eventCommandService.updateEvent(eventId, request, images); - } - - @DeleteMapping("/{eventId}") - @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteEvent(@PathVariable final Long eventId) { - eventCommandService.deleteEvent(eventId); - } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/report/api/ReportApi.java b/backend/emm-sale/src/main/java/com/emmsale/report/api/ReportApi.java index 3779984ca..2754f24e5 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/report/api/ReportApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/report/api/ReportApi.java @@ -2,14 +2,10 @@ import com.emmsale.member.domain.Member; import com.emmsale.report.application.ReportCommandService; -import com.emmsale.report.application.ReportQueryService; import com.emmsale.report.application.dto.ReportCreateRequest; import com.emmsale.report.application.dto.ReportCreateResponse; -import com.emmsale.report.application.dto.ReportFindResponse; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseStatus; @@ -20,7 +16,6 @@ public class ReportApi { private final ReportCommandService reportCommandService; - private final ReportQueryService reportQueryService; @PostMapping("/reports") @ResponseStatus(HttpStatus.CREATED) @@ -28,9 +23,4 @@ public ReportCreateResponse create(@RequestBody final ReportCreateRequest report final Member member) { return reportCommandService.create(reportRequest, member); } - - @GetMapping("/reports") - public List findReports() { - return reportQueryService.findReports(); - } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/tag/api/TagApi.java b/backend/emm-sale/src/main/java/com/emmsale/tag/api/TagApi.java index 0457dda7a..3534659b6 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/tag/api/TagApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/tag/api/TagApi.java @@ -1,16 +1,11 @@ package com.emmsale.tag.api; -import com.emmsale.tag.application.TagCommandService; import com.emmsale.tag.application.TagQueryService; -import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -20,15 +15,9 @@ public class TagApi { private final TagQueryService queryService; - private final TagCommandService commandService; @GetMapping public ResponseEntity> findAll() { return ResponseEntity.ok(queryService.findAll()); } - - @PostMapping - public ResponseEntity create(@RequestBody final TagRequest tagRequest) { - return ResponseEntity.status(HttpStatus.CREATED).body(commandService.addTag(tagRequest)); - } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/activity/application/ActivityCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java similarity index 82% rename from backend/emm-sale/src/test/java/com/emmsale/activity/application/ActivityCommandServiceTest.java rename to backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java index b71f3117b..c99823578 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/activity/application/ActivityCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java @@ -1,4 +1,4 @@ -package com.emmsale.activity.application; +package com.emmsale.admin.activity.application; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -26,19 +26,19 @@ void findActivity() { final String activityName = "DDD"; final ActivityAddRequest request = new ActivityAddRequest(ActivityType.CLUB, activityName); final ActivityResponse expected = new ActivityResponse( - 7L, - ActivityType.CLUB.getValue(), - activityName + 7L, + ActivityType.CLUB.getValue(), + activityName ); //when final ActivityResponse actual - = activityCommandService.addActivity(request); + = activityCommandService.addActivity(request); //then assertThat(actual) - .usingRecursiveComparison() - .isEqualTo(expected); + .usingRecursiveComparison() + .isEqualTo(expected); } @Test @@ -54,7 +54,7 @@ void findActivity_duplicate_fail() { //then assertThatThrownBy(actual) - .isInstanceOf(ActivityException.class) - .hasMessage(ActivityExceptionType.ALEADY_EXIST_ACTIVITY.errorMessage()); + .isInstanceOf(ActivityException.class) + .hasMessage(ActivityExceptionType.ALEADY_EXIST_ACTIVITY.errorMessage()); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java similarity index 85% rename from backend/emm-sale/src/test/java/com/emmsale/event/application/EventCommandServiceTest.java rename to backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java index d16ada5a2..06eb1eb2b 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java @@ -1,8 +1,6 @@ -package com.emmsale.event.application; +package com.emmsale.admin.event.application; -import static com.emmsale.event.EventFixture.AI_아이디어_공모전; import static com.emmsale.event.EventFixture.AI_컨퍼런스; -import static com.emmsale.event.EventFixture.구름톤; import static com.emmsale.event.EventFixture.모바일_컨퍼런스; import static com.emmsale.event.EventFixture.안드로이드_컨퍼런스; import static com.emmsale.event.EventFixture.웹_컨퍼런스; @@ -43,7 +41,6 @@ import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.domain.Tag; import com.emmsale.tag.domain.TagRepository; -import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @@ -58,35 +55,6 @@ class EventCommandServiceTest extends ServiceIntegrationTestHelper { - private static final EventResponse 인프콘_2023 = new EventResponse(null, "인프콘 2023", - null, null, null, null, null, "코엑스", List.of("백엔드"), - "이미지1", EventType.CONFERENCE.name(), List.of(), "인프런", PaymentType.PAID.getValue(), - EventMode.OFFLINE.getValue()); - private static final EventResponse 웹_컨퍼런스 = new EventResponse(null, "웹 컨퍼런스", null, - null, null, - null, null, "코엑스", List.of("백엔드"), "이미지1", EventType.CONFERENCE.name(), - List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); - private static final EventResponse 안드로이드_컨퍼런스 = new EventResponse(null, "안드로이드 컨퍼런스", - null, null, null, null, null, "코엑스", List.of("백엔드"), - "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), - EventMode.ONLINE.getValue()); - private static final EventResponse AI_컨퍼런스 = new EventResponse(null, "AI 컨퍼런스", - null, null, null, null, null, "코엑스", List.of("백엔드"), - "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), - EventMode.ONLINE.getValue()); - private static final EventResponse 모바일_컨퍼런스 = new EventResponse(null, "모바일 컨퍼런스", - null, null, null, null, null, "코엑스", List.of("백엔드"), - "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), - EventMode.ONLINE.getValue()); - private static final EventResponse AI_아이디어_공모전 = new EventResponse(null, - "AI 아이디어 공모전", null, null, null, null, null, "코엑스", - List.of("백엔드"), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", - PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); - private static final EventResponse 구름톤 = new EventResponse(null, "구름톤", null, - null, null, null, null, "코엑스", List.of("백엔드"), - "이미지1", EventType.COMPETITION.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), - EventMode.ONLINE.getValue()); - @Autowired private EventCommandService eventCommandService; @Autowired @@ -113,8 +81,6 @@ void init() { final Event 모바일_컨퍼런스 = eventRepository.save(모바일_컨퍼런스()); final Event 안드로이드_컨퍼런스 = eventRepository.save(안드로이드_컨퍼런스()); final Event 웹_컨퍼런스 = eventRepository.save(웹_컨퍼런스()); - final Event AI_아이디어_공모전 = eventRepository.save(AI_아이디어_공모전()); - final Event 구름톤 = eventRepository.save(구름톤()); eventTagRepository.saveAll(List.of( new EventTag(인프콘_2023, 백엔드), new EventTag(인프콘_2023, 프론트엔드), new EventTag(인프콘_2023, 안드로이드), @@ -157,11 +123,9 @@ class AddEvent { private final String eventName = "새로운 이름"; private final String eventLocation = "새로운 장소"; private final String eventInformationUrl = "https://새로운-상세-URL.com"; - private final String imageUrl = "https://image.com"; private final PaymentType paymentType = PaymentType.FREE_PAID; private final EventMode eventMode = EventMode.ON_OFFLINE; private final EventType type = EventType.CONFERENCE; - private final LocalDate now = LocalDate.now(); private final String organization = "행사기관"; @Test @@ -287,7 +251,6 @@ class UpdateEvent { private final String newName = "새로운 이름"; private final String newLocation = "새로운 장소"; private final String newInformationUrl = "https://새로운-상세-URL.com"; - private final LocalDate now = LocalDate.now(); private final PaymentType paymentType = PaymentType.FREE_PAID; private final EventMode eventMode = EventMode.ON_OFFLINE; private final String organization = "행사기관"; @@ -464,4 +427,4 @@ void deleteEventWithNotExistsEventTest() { } } -} \ No newline at end of file +} diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceEventIntegrationTestQuery.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java similarity index 99% rename from backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceEventIntegrationTestQuery.java rename to backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java index be4533b48..7a5e48cf6 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventServiceEventIntegrationTestQuery.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java @@ -1,4 +1,4 @@ -package com.emmsale.event.application; +package com.emmsale.admin.event.application; import static com.emmsale.tag.TagFixture.IOS; import static com.emmsale.tag.TagFixture.백엔드; diff --git a/backend/emm-sale/src/test/java/com/emmsale/report/application/ReportQueryServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java similarity index 96% rename from backend/emm-sale/src/test/java/com/emmsale/report/application/ReportQueryServiceTest.java rename to backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java index f8312ebac..4de6768f2 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/report/application/ReportQueryServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java @@ -1,4 +1,4 @@ -package com.emmsale.report.application; +package com.emmsale.admin.report.application; import static com.emmsale.event.EventFixture.eventFixture; @@ -12,6 +12,7 @@ import com.emmsale.helper.ServiceIntegrationTestHelper; import com.emmsale.member.domain.Member; import com.emmsale.member.domain.MemberRepository; +import com.emmsale.report.application.ReportCommandService; import com.emmsale.report.application.dto.ReportCreateRequest; import com.emmsale.report.application.dto.ReportCreateResponse; import com.emmsale.report.application.dto.ReportFindResponse; diff --git a/backend/emm-sale/src/test/java/com/emmsale/tag/application/TagCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java similarity index 97% rename from backend/emm-sale/src/test/java/com/emmsale/tag/application/TagCommandServiceTest.java rename to backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java index 0435c2830..4fdd936d6 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/tag/application/TagCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java @@ -1,4 +1,4 @@ -package com.emmsale.tag.application; +package com.emmsale.admin.tag.application; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; From d44fb3657c70e95afbdc3a6023dda7d12d8d6fb0 Mon Sep 17 00:00:00 2001 From: amaran-th Date: Sun, 19 Nov 2023 20:08:37 +0900 Subject: [PATCH 02/20] =?UTF-8?q?feat:=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 아이디와 패스워드가 설정된 값과 일치하면 관리자 토큰 발급 #156 --- .../src/documentTest/asciidoc/index.adoc | 14 +++ .../java/com/emmsale/LoginApiTest.java | 40 ++++++- .../java/com/emmsale/MockMvcTestHelper.java | 3 + .../admin/login/api/AdminLoginApi.java | 26 +++++ .../login/application/AdminLoginService.java | 45 ++++++++ .../application/dto/AdminLoginRequest.java | 13 +++ .../application/dto/AdminTokenResponse.java | 11 ++ .../login/exception/LoginExceptionType.java | 12 +++ .../src/main/resources/application.yml | 4 + backend/emm-sale/src/main/resources/data.sql | 6 ++ .../application/AdminLoginServiceTest.java | 100 ++++++++++++++++++ 11 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/login/api/AdminLoginApi.java create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/login/application/AdminLoginService.java create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminTokenResponse.java create mode 100644 backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java diff --git a/backend/emm-sale/src/documentTest/asciidoc/index.adoc b/backend/emm-sale/src/documentTest/asciidoc/index.adoc index 701dc6e70..419b2577e 100644 --- a/backend/emm-sale/src/documentTest/asciidoc/index.adoc +++ b/backend/emm-sale/src/documentTest/asciidoc/index.adoc @@ -632,6 +632,20 @@ include::{snippets}/delete-notifications/http-response.adoc[] == 관리자 API +=== `POST` : 관리자 로그인 + +.HTTP request +include::{snippets}/admin-login-snippet/http-request.adoc[] + +.HTTP request 설명 +include::{snippets}/admin-login-snippet/request-fields.adoc[] + +.HTTP response +include::{snippets}/admin-login-snippet/http-response.adoc[] + +.HTTP response 설명 +include::{snippets}/admin-login-snippet/response-fields.adoc[] + === `POST` : 행사 생성 .HTTP request diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/LoginApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/LoginApiTest.java index 01b3aae9c..7a146a28d 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/LoginApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/LoginApiTest.java @@ -1,7 +1,9 @@ package com.emmsale; +import static org.mockito.ArgumentMatchers.any; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; 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.requestParameters; @@ -9,18 +11,23 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.emmsale.admin.login.api.AdminLoginApi; +import com.emmsale.admin.login.application.dto.AdminLoginRequest; +import com.emmsale.admin.login.application.dto.AdminTokenResponse; import com.emmsale.login.api.LoginApi; import com.emmsale.login.application.dto.TokenResponse; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.mockito.BDDMockito; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.restdocs.payload.RequestFieldsSnippet; import org.springframework.restdocs.payload.ResponseFieldsSnippet; import org.springframework.restdocs.request.RequestParametersSnippet; import org.springframework.test.web.servlet.ResultActions; -@WebMvcTest(LoginApi.class) +@WebMvcTest({LoginApi.class, AdminLoginApi.class}) class LoginApiTest extends MockMvcTestHelper { @Test @@ -62,4 +69,35 @@ void illegalLoginTest() throws Exception { result.andExpect(status().isBadRequest()) .andDo(print()); } + + @Test + @DisplayName("id와 password가 유효할 경우 200과 함께 AdminTokenResponse를 반환해 준다.") + void availableAdminLoginTest() throws Exception { + // given + final AdminLoginRequest request = new AdminLoginRequest("관리자 id", "관리자 password"); + final AdminTokenResponse adminTokenResponse = new AdminTokenResponse("access_token"); + + BDDMockito.given(adminLoginService.createAdminToken(any())).willReturn(adminTokenResponse); + + final RequestFieldsSnippet requestFields = requestFields( + fieldWithPath("id").type(JsonFieldType.STRING).description("관리자 로그인 id"), + fieldWithPath("password").type(JsonFieldType.STRING).description("관리자 로그인 password") + ); + + final ResponseFieldsSnippet responseFields = responseFields( + fieldWithPath("accessToken").type(JsonFieldType.STRING).description("관리자 Access Token 값") + ); + + // when + final ResultActions result = mockMvc.perform( + post("/admin/login") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(request)) + ); + + // then + result.andExpect(status().isOk()) + .andDo(print()) + .andDo(document("admin-login-snippet", requestFields, responseFields)); + } } diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java b/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java index a5ee07bab..d3debbb60 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/MockMvcTestHelper.java @@ -6,6 +6,7 @@ import com.emmsale.activity.application.ActivityQueryService; import com.emmsale.admin.activity.application.ActivityCommandService; import com.emmsale.admin.event.application.EventCommandService; +import com.emmsale.admin.login.application.AdminLoginService; import com.emmsale.admin.report.application.ReportQueryService; import com.emmsale.admin.tag.application.TagCommandService; import com.emmsale.block.application.BlockCommandService; @@ -81,6 +82,8 @@ abstract class MockMvcTestHelper { @MockBean protected LoginService loginService; @MockBean + protected AdminLoginService adminLoginService; + @MockBean protected EventQueryService eventQueryService; @MockBean protected EventCommandService eventCommandService; diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/api/AdminLoginApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/api/AdminLoginApi.java new file mode 100644 index 000000000..3256fb6da --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/api/AdminLoginApi.java @@ -0,0 +1,26 @@ +package com.emmsale.admin.login.api; + +import com.emmsale.admin.login.application.AdminLoginService; +import com.emmsale.admin.login.application.dto.AdminLoginRequest; +import com.emmsale.admin.login.application.dto.AdminTokenResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/admin/login") +public class AdminLoginApi { + + private final AdminLoginService adminLoginService; + + public AdminLoginApi(final AdminLoginService adminLoginService) { + this.adminLoginService = adminLoginService; + } + + @PostMapping + public ResponseEntity login(@RequestBody final AdminLoginRequest request) { + return ResponseEntity.ok().body(adminLoginService.createAdminToken(request)); + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/AdminLoginService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/AdminLoginService.java new file mode 100644 index 000000000..4eee73f9c --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/AdminLoginService.java @@ -0,0 +1,45 @@ +package com.emmsale.admin.login.application; + +import com.emmsale.admin.login.application.dto.AdminLoginRequest; +import com.emmsale.admin.login.application.dto.AdminTokenResponse; +import com.emmsale.login.exception.LoginException; +import com.emmsale.login.exception.LoginExceptionType; +import com.emmsale.login.utils.JwtTokenProvider; +import javax.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@Transactional +@RequiredArgsConstructor +public class AdminLoginService { + + private final JwtTokenProvider tokenProvider; + @Value("${data.admin_login.id}") + private String adminId; + @Value("${data.admin_login.password}") + private String adminPassword; + @Value("${data.admin_login.member_id}") + private Long adminMemberId; + + public AdminTokenResponse createAdminToken(final AdminLoginRequest request) { + validateNotNullRequest(request); + validateAdminLoginInformation(request); + final String accessToken = tokenProvider.createToken(String.valueOf(adminMemberId)); + + return new AdminTokenResponse(accessToken); + } + + private void validateNotNullRequest(final AdminLoginRequest request) { + if (request == null) { + throw new LoginException(LoginExceptionType.NOT_FOUND_ADMIN_LOGIN_INFORMATION); + } + } + + private void validateAdminLoginInformation(final AdminLoginRequest request) { + if (!(request.getId().equals(adminId) && request.getPassword().equals(adminPassword))) { + throw new LoginException(LoginExceptionType.INVALID_ADMIN_LOGIN_INFORMATION); + } + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java new file mode 100644 index 000000000..54706ff2b --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java @@ -0,0 +1,13 @@ +package com.emmsale.admin.login.application.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class AdminLoginRequest { + + final String id; + final String password; + +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminTokenResponse.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminTokenResponse.java new file mode 100644 index 000000000..120c07e91 --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminTokenResponse.java @@ -0,0 +1,11 @@ +package com.emmsale.admin.login.application.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class AdminTokenResponse { + + private final String accessToken; +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java b/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java index 414d3a738..c51365b7f 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java +++ b/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java @@ -32,6 +32,18 @@ public enum LoginExceptionType implements BaseExceptionType { INVALID_ACCESS_TOKEN_TYPE( HttpStatus.BAD_REQUEST, "Access Token Type이 올바르지 않습니다." + ), + NOT_FOUND_ADMIN_LOGIN_INFORMATION( + HttpStatus.BAD_REQUEST, + "관리자 로그인 정보를 찾을 수 없습니다." + ), + INVALID_ADMIN_LOGIN_INFORMATION( + HttpStatus.BAD_REQUEST, + "관리자 아이디 또는 비밀번호가 올바르지 않습니다." + ), + INVALID_ADMIN_ACCESS_TOKEN( + HttpStatus.BAD_REQUEST, + "관리자 토큰이 유효하지 않습니다." ); private final HttpStatus httpStatus; diff --git a/backend/emm-sale/src/main/resources/application.yml b/backend/emm-sale/src/main/resources/application.yml index 652a9a99e..9a4ac3ef9 100644 --- a/backend/emm-sale/src/main/resources/application.yml +++ b/backend/emm-sale/src/main/resources/application.yml @@ -52,6 +52,10 @@ firebase: data: admin-url: http://localhost:3000 + admin_login: + id: admin + password: 1234 + member_id: 3 cloud: aws: diff --git a/backend/emm-sale/src/main/resources/data.sql b/backend/emm-sale/src/main/resources/data.sql index 364184b07..1c4e47221 100644 --- a/backend/emm-sale/src/main/resources/data.sql +++ b/backend/emm-sale/src/main/resources/data.sql @@ -46,6 +46,12 @@ insert into member(id, name, image_url, open_profile_url, description, github_id values (2, 'member2', 'https://imageurl.com', 'https://openprofileurl.com', '반갑습니다.', 2, 'amaran-th22', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()); +insert into member(id, name, image_url, open_profile_url, description, github_id, github_username, + created_at, + updated_at) +values (3, 'admin', 'https://imageurl.com', 'https://openprofileurl.com', '반갑습니다.', 3, + 'amaran-th22', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()); + insert into member_activity(id, activity_id, member_id, created_at, updated_at) values (1, 1, 1, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()); diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java new file mode 100644 index 000000000..52aaffed0 --- /dev/null +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java @@ -0,0 +1,100 @@ +package com.emmsale.admin.login.application; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.BDDMockito.given; + +import com.emmsale.admin.login.application.dto.AdminLoginRequest; +import com.emmsale.admin.login.application.dto.AdminTokenResponse; +import com.emmsale.helper.ServiceIntegrationTestHelper; +import com.emmsale.login.exception.LoginException; +import com.emmsale.login.exception.LoginExceptionType; +import com.emmsale.login.utils.JwtTokenProvider; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +@SpringBootTest +class AdminLoginServiceTest extends ServiceIntegrationTestHelper { + + @Autowired + private AdminLoginService adminLoginService; + @MockBean + private JwtTokenProvider tokenProvider; + @Value("${data.admin_login.id}") + private String adminId; + @Value("${data.admin_login.password}") + private String adminPassword; + @Value("${data.admin_login.member_id}") + private Long adminMemberId; + + @Test + @DisplayName("관리자 아이디, 패스워드로 사용자를 조회하여 토큰을 생성한다.") + void createAdminToken_success() { + // given + final Long memberId = adminMemberId; + final AdminLoginRequest request = new AdminLoginRequest(adminId, adminPassword); + final String expectAccessToken = "expect_access_token"; + given(tokenProvider.createToken(String.valueOf(memberId))).willReturn(expectAccessToken); + + // when + final AdminTokenResponse actualToken = adminLoginService.createAdminToken(request); + + // then + assertEquals(expectAccessToken, actualToken.getAccessToken()); + } + + @Test + @DisplayName("관리자 정보 요청이 null이면 예외를 반환한다.") + void createAdminToken_fail_not_found_request() { + // given + final LoginExceptionType expectExceptionType = LoginExceptionType.NOT_FOUND_ADMIN_LOGIN_INFORMATION; + + // when + final ThrowingCallable actual = () -> adminLoginService.createAdminToken(null); + + // then + Assertions.assertThatThrownBy(actual) + .isInstanceOf(LoginException.class) + .hasMessage(expectExceptionType.errorMessage()); + } + + @Test + @DisplayName("관리자 아이디가 올바르지 않으면 예외를 반환한다.") + void createAdminToken_fail_invalid_id() { + // given + final AdminLoginRequest request = new AdminLoginRequest("invalid", adminPassword); + final LoginExceptionType expectExceptionType = LoginExceptionType.INVALID_ADMIN_LOGIN_INFORMATION; + + // when + final ThrowingCallable actual = () -> adminLoginService.createAdminToken( + request); + + // then + Assertions.assertThatThrownBy(actual) + .isInstanceOf(LoginException.class) + .hasMessage(expectExceptionType.errorMessage()); + } + + @Test + @DisplayName("관리자 패스워드가 올바르지 않으면 예외를 반환한다.") + void createAdminToken_fail_invalid_password() { + // given + final AdminLoginRequest request = new AdminLoginRequest(adminId, "invalid"); + final LoginExceptionType expectExceptionType = LoginExceptionType.INVALID_ADMIN_LOGIN_INFORMATION; + + // when + final ThrowingCallable actual = () -> adminLoginService.createAdminToken( + request); + + // then + Assertions.assertThatThrownBy(actual) + .isInstanceOf(LoginException.class) + .hasMessage(expectExceptionType.errorMessage()); + } + +} \ No newline at end of file From dc9acef9c3c391a2085c48ed38c0f33f5a642193 Mon Sep 17 00:00:00 2001 From: amaran-th Date: Mon, 20 Nov 2023 16:41:02 +0900 Subject: [PATCH 03/20] =?UTF-8?q?feat:=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EA=B2=80=EC=A6=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 헤더에 관리자 토큰이 포함되어있지 않으면 예외를 반환 #156 --- .../java/com/emmsale/ActivityApiTest.java | 6 +- .../java/com/emmsale/EventApiTest.java | 24 +++-- .../java/com/emmsale/ReportApiTest.java | 7 +- .../java/com/emmsale/TagApiTest.java | 5 +- .../admin/activity/api/AdminActivityApi.java | 6 +- .../application/ActivityCommandService.java | 6 +- .../admin/event/api/AdminEventApi.java | 17 ++-- .../application/EventCommandService.java | 11 ++- .../admin/login/utils/AdminValidator.java | 24 +++++ .../admin/report/api/AdminReportApi.java | 5 +- .../application/ReportQueryService.java | 6 +- .../emmsale/admin/tag/api/AdminTagApi.java | 6 +- .../tag/application/TagCommandService.java | 7 +- .../ActivityCommandServiceTest.java | 30 +++++- .../application/EventCommandServiceTest.java | 97 +++++++++++++++++-- ...EventServiceEventIntegrationTestQuery.java | 7 +- .../application/ReportQueryServiceTest.java | 19 +++- .../application/TagCommandServiceTest.java | 26 ++++- .../com/emmsale/member/MemberFixture.java | 26 ++++- 19 files changed, 284 insertions(+), 51 deletions(-) create mode 100644 backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java index 867906f8c..c588da6d9 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/ActivityApiTest.java @@ -14,6 +14,7 @@ import com.emmsale.activity.application.dto.ActivityResponse; import com.emmsale.activity.domain.ActivityType; import com.emmsale.admin.activity.api.AdminActivityApi; +import com.emmsale.member.domain.Member; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -72,8 +73,10 @@ void addTag() throws Exception { ActivityType.CLUB.getValue(), "DND" ); + final String accessToken = "Bearer accessToken"; - when(activityCommandService.addActivity(any(ActivityAddRequest.class))).thenReturn(response); + when(activityCommandService.addActivity(any(ActivityAddRequest.class), + any(Member.class))).thenReturn(response); final ResponseFieldsSnippet responseFields = responseFields( fieldWithPath("id").type(JsonFieldType.NUMBER).description("활동 식별자"), @@ -83,6 +86,7 @@ void addTag() throws Exception { //when & then mockMvc.perform(post("/admin/activities") + .header("Authorization", accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isCreated()) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java index 1dfd3ea7a..0ed7356ec 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java @@ -1,5 +1,6 @@ package com.emmsale; +import static com.emmsale.member.MemberFixture.adminMember; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -20,6 +21,7 @@ import com.emmsale.event.domain.EventMode; import com.emmsale.event.domain.EventType; import com.emmsale.event.domain.PaymentType; +import com.emmsale.member.domain.Member; import com.emmsale.tag.TagFixture; import com.emmsale.tag.application.dto.TagRequest; import java.nio.charset.StandardCharsets; @@ -56,6 +58,8 @@ @WebMvcTest({EventApi.class, AdminEventApi.class}) class EventApiTest extends MockMvcTestHelper { + private static final String accessToken = "Bearer accessToken"; + private static final ResponseFieldsSnippet EVENT_DETAIL_RESPONSE_FILED = PayloadDocumentation.responseFields( fieldWithPath("id").type(JsonFieldType.NUMBER).description("event 식별자"), fieldWithPath("name").type(JsonFieldType.STRING) @@ -233,7 +237,8 @@ void updateEventTest() throws Exception { "image1.jpg", request.getType().toString(), List.of("imageUrl1", "imageUrl2"), "행사기관", "유료", "온라인"); - Mockito.when(eventCommandService.updateEvent(eq(eventId), any(EventDetailRequest.class), any())) + Mockito.when( + eventCommandService.updateEvent(eq(eventId), any(EventDetailRequest.class), any(), any())) .thenReturn(response); final String contents = objectMapper.writeValueAsString(request); @@ -266,7 +271,7 @@ void updateEventTest() throws Exception { .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))); - final ResultActions result = mockMvc.perform(builder); + final ResultActions result = mockMvc.perform(builder.header("Authorization", accessToken)); //when & then result.andExpect(status().isOk()) @@ -283,10 +288,11 @@ void deleteEventTest() throws Exception { //given final long eventId = 1L; - Mockito.doNothing().when(eventCommandService).deleteEvent(eventId); + Mockito.doNothing().when(eventCommandService).deleteEvent(eventId, adminMember()); //when final ResultActions result = mockMvc.perform( - delete("/admin/events/" + eventId)); + delete("/admin/events/" + eventId) + .header("Authorization", accessToken)); //then result.andExpect(status().isNoContent()) @@ -335,7 +341,8 @@ void addEventTest() throws Exception { "image1.jpg", request.getType().toString(), List.of("imageUrl1", "imageUrl2"), "행사기관", "무료", "오프라인"); - Mockito.when(eventCommandService.addEvent(any(EventDetailRequest.class), any())) + Mockito.when( + eventCommandService.addEvent(any(EventDetailRequest.class), any(), any(Member.class))) .thenReturn(response); final String contents = objectMapper.writeValueAsString(request); @@ -367,7 +374,7 @@ void addEventTest() throws Exception { .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))); - final ResultActions result = mockMvc.perform(builder); + final ResultActions result = mockMvc.perform(builder.header("Authorization", accessToken)); //then result.andExpect(status().isCreated()) @@ -413,6 +420,7 @@ void addEventWithEmptyNameTest(final String eventName) throws Exception { .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))) + .header("Authorization", accessToken) ) .andExpect(status().isBadRequest()); } @@ -454,6 +462,7 @@ void addEventWithEmptyLocationTest(final String eventLocation) throws Exception .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))) + .header("Authorization", accessToken) ) .andExpect(status().isBadRequest()); } @@ -496,6 +505,7 @@ void addEventWithInvalidInformationUrlTest(final String informationUrl) throws E .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))) + .header("Authorization", accessToken) ) .andExpect(status().isBadRequest()); } @@ -544,6 +554,7 @@ void addEventWithUnformattedStartDateTimeTest(final String startDateTime) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))) + .header("Authorization", accessToken) ) .andExpect(status().isBadRequest()); } @@ -591,6 +602,7 @@ void addEventWithUnformattedEndDateTimeTest(final String endDateTime) throws Exc .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( StandardCharsets.UTF_8))) + .header("Authorization", accessToken) ) .andExpect(status().isBadRequest()); } diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java index ef572149a..8658fd3a1 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/ReportApiTest.java @@ -11,6 +11,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.emmsale.admin.report.api.AdminReportApi; +import com.emmsale.member.domain.Member; import com.emmsale.report.api.ReportApi; import com.emmsale.report.application.dto.ReportCreateRequest; import com.emmsale.report.application.dto.ReportCreateResponse; @@ -75,6 +76,7 @@ void addReport() throws Exception { @DisplayName("신고 목록을 조회할 수 있다.") void findReports() throws Exception { // given + final String accessToken = "Bearer accessToken"; final ResponseFieldsSnippet responseFields = responseFields( fieldWithPath("[].id").type(JsonFieldType.NUMBER).description("신고 id"), fieldWithPath("[].reporterId").type(JsonFieldType.NUMBER).description("신고자의 Id"), @@ -98,10 +100,11 @@ void findReports() throws Exception { ); - when(reportQueryService.findReports()).thenReturn(reportFindResponse); + when(reportQueryService.findReports(any(Member.class))).thenReturn(reportFindResponse); // when & then - mockMvc.perform(get("/admin/reports")) + mockMvc.perform(get("/admin/reports") + .header("Authorization", accessToken)) .andExpect(status().isOk()) .andDo(document("find-reports", responseFields)); } diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java index 03d92eecc..67ec043b0 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/TagApiTest.java @@ -11,6 +11,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.emmsale.admin.tag.api.AdminTagApi; +import com.emmsale.member.domain.Member; import com.emmsale.tag.api.TagApi; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; @@ -58,8 +59,9 @@ void addTag() throws Exception { ); final TagRequest request = new TagRequest("프론트"); final TagResponse response = new TagResponse(3L, "프론트"); + final String accessToken = "Bearer accessToken"; - when(tagCommandService.addTag(any(TagRequest.class))).thenReturn(response); + when(tagCommandService.addTag(any(TagRequest.class), any(Member.class))).thenReturn(response); final ResponseFieldsSnippet responseFields = responseFields( fieldWithPath("id").type(JsonFieldType.NUMBER).description("태그 식별자"), @@ -68,6 +70,7 @@ void addTag() throws Exception { //when & then mockMvc.perform(post("/admin/tags") + .header("Authorization", accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isCreated()) diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java index 320118055..26c990eca 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/api/AdminActivityApi.java @@ -3,6 +3,7 @@ import com.emmsale.activity.application.dto.ActivityAddRequest; import com.emmsale.activity.application.dto.ActivityResponse; import com.emmsale.admin.activity.application.ActivityCommandService; +import com.emmsale.member.domain.Member; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -20,9 +21,10 @@ public class AdminActivityApi { @PostMapping public ResponseEntity create( - @RequestBody final ActivityAddRequest request + @RequestBody final ActivityAddRequest request, + final Member admin ) { return ResponseEntity.status(HttpStatus.CREATED) - .body(activityCommandService.addActivity(request)); + .body(activityCommandService.addActivity(request, admin)); } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java index a60b51aaa..686d0cb34 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/activity/application/ActivityCommandService.java @@ -1,11 +1,14 @@ package com.emmsale.admin.activity.application; +import static com.emmsale.admin.login.utils.AdminValidator.validateAuthorization; + import com.emmsale.activity.application.dto.ActivityAddRequest; import com.emmsale.activity.application.dto.ActivityResponse; import com.emmsale.activity.domain.Activity; import com.emmsale.activity.domain.ActivityRepository; import com.emmsale.activity.exception.ActivityException; import com.emmsale.activity.exception.ActivityExceptionType; +import com.emmsale.member.domain.Member; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,7 +20,8 @@ public class ActivityCommandService { private final ActivityRepository activityRepository; - public ActivityResponse addActivity(final ActivityAddRequest request) { + public ActivityResponse addActivity(final ActivityAddRequest request, final Member admin) { + validateAuthorization(admin); final String name = request.getName(); validateAlreadyExist(name); final Activity activity = new Activity(request.getActivityType(), name); diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java index 2c06f1166..7d5647833 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/event/api/AdminEventApi.java @@ -3,6 +3,7 @@ import com.emmsale.admin.event.application.EventCommandService; import com.emmsale.event.application.dto.EventDetailRequest; import com.emmsale.event.application.dto.EventResponse; +import com.emmsale.member.domain.Member; import java.util.List; import javax.validation.Valid; import lombok.RequiredArgsConstructor; @@ -28,21 +29,25 @@ public class AdminEventApi { @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @ResponseStatus(HttpStatus.CREATED) public EventResponse addEvent(@RequestPart @Valid final EventDetailRequest request, - @RequestPart final List images) { - return eventCommandService.addEvent(request, images); + @RequestPart final List images, + final Member admin + ) { + return eventCommandService.addEvent(request, images, admin); } @PutMapping(path = "/{eventId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @ResponseStatus(HttpStatus.OK) public EventResponse updateEvent(@PathVariable final Long eventId, @RequestPart @Valid final EventDetailRequest request, - @RequestPart final List images) { - return eventCommandService.updateEvent(eventId, request, images); + @RequestPart final List images, + final Member admin + ) { + return eventCommandService.updateEvent(eventId, request, images, admin); } @DeleteMapping("/{eventId}") @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteEvent(@PathVariable final Long eventId) { - eventCommandService.deleteEvent(eventId); + public void deleteEvent(@PathVariable final Long eventId, final Member admin) { + eventCommandService.deleteEvent(eventId, admin); } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java index c6c322be4..244217c33 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/event/application/EventCommandService.java @@ -1,5 +1,6 @@ package com.emmsale.admin.event.application; +import static com.emmsale.admin.login.utils.AdminValidator.validateAuthorization; import static com.emmsale.event.exception.EventExceptionType.NOT_FOUND_EVENT; import static java.util.stream.Collectors.toList; @@ -14,6 +15,7 @@ import com.emmsale.image.application.ImageCommandService; import com.emmsale.image.domain.AllImagesOfContent; import com.emmsale.image.domain.ImageType; +import com.emmsale.member.domain.Member; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.domain.Tag; import com.emmsale.tag.domain.TagRepository; @@ -36,7 +38,8 @@ public class EventCommandService { private final ImageCommandService imageCommandService; public EventResponse addEvent(final EventDetailRequest request, - final List images) { + final List images, final Member admin) { + validateAuthorization(admin); final Event event = eventRepository.save(request.toEvent()); final List tags = findAllPersistTagsOrElseThrow(request.getTags()); event.addAllEventTags(tags); @@ -49,7 +52,8 @@ public EventResponse addEvent(final EventDetailRequest request, } public EventResponse updateEvent(final Long eventId, final EventDetailRequest request, - final List images) { + final List images, final Member admin) { + validateAuthorization(admin); final Event event = eventRepository.findById(eventId) .orElseThrow(() -> new EventException(NOT_FOUND_EVENT)); @@ -77,7 +81,8 @@ public EventResponse updateEvent(final Long eventId, final EventDetailRequest re return EventResponse.from(updatedEvent, savedImages); } - public void deleteEvent(final Long eventId) { + public void deleteEvent(final Long eventId, final Member admin) { + validateAuthorization(admin); if (!eventRepository.existsById(eventId)) { throw new EventException(NOT_FOUND_EVENT); } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java new file mode 100644 index 000000000..fa58c5457 --- /dev/null +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java @@ -0,0 +1,24 @@ +package com.emmsale.admin.login.utils; + +import com.emmsale.login.exception.LoginException; +import com.emmsale.login.exception.LoginExceptionType; +import com.emmsale.member.domain.Member; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class AdminValidator { + + private static Long adminMemberId; + + public static void validateAuthorization(final Member admin) { + if (admin.isNotMe(adminMemberId)) { + throw new LoginException(LoginExceptionType.INVALID_ACCESS_TOKEN); + } + } + + @Value("${data.admin_login.member_id}") + public void setAdminMemberId(final Long adminMemberId) { + AdminValidator.adminMemberId = adminMemberId; + } +} diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java index 42b175317..00c9c9895 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/report/api/AdminReportApi.java @@ -1,6 +1,7 @@ package com.emmsale.admin.report.api; import com.emmsale.admin.report.application.ReportQueryService; +import com.emmsale.member.domain.Member; import com.emmsale.report.application.dto.ReportFindResponse; import java.util.List; import lombok.RequiredArgsConstructor; @@ -16,7 +17,7 @@ public class AdminReportApi { private final ReportQueryService reportQueryService; @GetMapping - public List findReports() { - return reportQueryService.findReports(); + public List findReports(final Member admin) { + return reportQueryService.findReports(admin); } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java index 831070c31..1535b0b45 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/report/application/ReportQueryService.java @@ -1,5 +1,8 @@ package com.emmsale.admin.report.application; +import static com.emmsale.admin.login.utils.AdminValidator.validateAuthorization; + +import com.emmsale.member.domain.Member; import com.emmsale.report.application.dto.ReportFindResponse; import com.emmsale.report.domain.repository.ReportRepository; import java.util.List; @@ -14,7 +17,8 @@ public class ReportQueryService { private final ReportRepository reportRepository; - public List findReports() { + public List findReports(final Member admin) { + validateAuthorization(admin); return ReportFindResponse.from(reportRepository.findAll()); } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java index 5c9c12fb0..182c050b2 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/api/AdminTagApi.java @@ -1,6 +1,7 @@ package com.emmsale.admin.tag.api; import com.emmsale.admin.tag.application.TagCommandService; +import com.emmsale.member.domain.Member; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; import lombok.RequiredArgsConstructor; @@ -19,7 +20,8 @@ public class AdminTagApi { private final TagCommandService commandService; @PostMapping - public ResponseEntity create(@RequestBody final TagRequest tagRequest) { - return ResponseEntity.status(HttpStatus.CREATED).body(commandService.addTag(tagRequest)); + public ResponseEntity create(@RequestBody final TagRequest tagRequest, + final Member admin) { + return ResponseEntity.status(HttpStatus.CREATED).body(commandService.addTag(tagRequest, admin)); } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java index 461435587..57ed1375e 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/tag/application/TagCommandService.java @@ -1,5 +1,8 @@ package com.emmsale.admin.tag.application; +import static com.emmsale.admin.login.utils.AdminValidator.validateAuthorization; + +import com.emmsale.member.domain.Member; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; import com.emmsale.tag.domain.Tag; @@ -17,7 +20,9 @@ public class TagCommandService { private final TagRepository tagRepository; - public TagResponse addTag(final TagRequest request) { + public TagResponse addTag(final TagRequest request, + final Member admin) { + validateAuthorization(admin); final String name = request.getName(); validateAlreadyExist(name); return TagResponse.from(tagRepository.save(new Tag(name))); diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java index c99823578..c44beb9b4 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java @@ -1,5 +1,7 @@ package com.emmsale.admin.activity.application; +import static com.emmsale.member.MemberFixture.adminMember; +import static com.emmsale.member.MemberFixture.generalMember; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -9,6 +11,8 @@ import com.emmsale.activity.exception.ActivityException; import com.emmsale.activity.exception.ActivityExceptionType; import com.emmsale.helper.ServiceIntegrationTestHelper; +import com.emmsale.login.exception.LoginException; +import com.emmsale.login.exception.LoginExceptionType; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -33,7 +37,7 @@ void findActivity() { //when final ActivityResponse actual - = activityCommandService.addActivity(request); + = activityCommandService.addActivity(request, adminMember()); //then assertThat(actual) @@ -43,18 +47,36 @@ void findActivity() { @Test @DisplayName("이미 존재하는 활동을 추가하면 예외를 반환한다.") - void findActivity_duplicate_fail() { + void findActivity_fail_duplicate() { //given final String activityName = "DDD"; final ActivityAddRequest request = new ActivityAddRequest(ActivityType.CLUB, activityName); - activityCommandService.addActivity(request); + activityCommandService.addActivity(request, adminMember()); //when - final ThrowingCallable actual = () -> activityCommandService.addActivity(request); + final ThrowingCallable actual = () -> activityCommandService.addActivity(request, + adminMember()); //then assertThatThrownBy(actual) .isInstanceOf(ActivityException.class) .hasMessage(ActivityExceptionType.ALEADY_EXIST_ACTIVITY.errorMessage()); } + + @Test + @DisplayName("관리자가 아닌 회원이 활동을 추가하면 예외를 반환한다.") + void findActivity_fail_authorization() { + //given + final String activityName = "DDD"; + final ActivityAddRequest request = new ActivityAddRequest(ActivityType.CLUB, activityName); + + //when + final ThrowingCallable actual = () -> activityCommandService.addActivity(request, + generalMember()); + + //then + assertThatThrownBy(actual) + .isInstanceOf(LoginException.class) + .hasMessage(LoginExceptionType.INVALID_ACCESS_TOKEN.errorMessage()); + } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java index 06eb1eb2b..85bed8fbe 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java @@ -11,6 +11,9 @@ import static com.emmsale.image.ImageFixture.행사_이미지1; import static com.emmsale.image.ImageFixture.행사_이미지2; import static com.emmsale.image.ImageFixture.행사_이미지3; +import static com.emmsale.login.exception.LoginExceptionType.INVALID_ACCESS_TOKEN; +import static com.emmsale.member.MemberFixture.adminMember; +import static com.emmsale.member.MemberFixture.generalMember; import static com.emmsale.tag.TagFixture.AI; import static com.emmsale.tag.TagFixture.IOS; import static com.emmsale.tag.TagFixture.백엔드; @@ -37,6 +40,7 @@ import com.emmsale.event.exception.EventException; import com.emmsale.helper.ServiceIntegrationTestHelper; import com.emmsale.image.domain.repository.ImageRepository; +import com.emmsale.login.exception.LoginException; import com.emmsale.notification.domain.Notification; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.domain.Tag; @@ -152,7 +156,7 @@ void addEventTest() { //when final EventResponse response = eventCommandService.addEvent(request, - mockMultipartFiles); + mockMultipartFiles, adminMember()); final Event savedEvent = eventRepository.findById(response.getId()).get(); //then @@ -198,7 +202,7 @@ void addEventWithStartDateTimeAfterBeforeDateTimeTest() { //when & then final EventException exception = assertThrowsExactly(EventException.class, - () -> eventCommandService.addEvent(request, mockMultipartFiles)); + () -> eventCommandService.addEvent(request, mockMultipartFiles, adminMember())); assertEquals(START_DATE_TIME_AFTER_END_DATE_TIME, exception.exceptionType()); } @@ -233,10 +237,39 @@ void addEventWithNotExistTagTest() { //when & then final EventException exception = assertThrowsExactly(EventException.class, - () -> eventCommandService.addEvent(request, mockMultipartFiles)); + () -> eventCommandService.addEvent(request, mockMultipartFiles, adminMember())); assertEquals(NOT_FOUND_TAG, exception.exceptionType()); } + + @Test + @DisplayName("관리자가 아닌 회원이 행사를 추가할 경우 LoginException이 발생한다.") + void addEvent_fail_authorization() { + //given + final EventDetailRequest request = new EventDetailRequest( + eventName, + eventLocation, + eventInformationUrl, + beforeDateTime, + afterDateTime, + beforeDateTime, + afterDateTime, + tagRequests, + type, + eventMode, + paymentType, + organization + ); + + doNothing().when(firebaseCloudMessageClient) + .sendMessageTo(any(Notification.class), anyLong()); + + //when & then + final LoginException exception = assertThrowsExactly(LoginException.class, + () -> eventCommandService.addEvent(request, mockMultipartFiles, generalMember())); + + assertEquals(INVALID_ACCESS_TOKEN, exception.exceptionType()); + } } @Nested @@ -282,7 +315,7 @@ void updateEventTest() { //when final EventResponse response = eventCommandService.updateEvent(eventId, updateRequest, - mockMultipartFiles); + mockMultipartFiles, adminMember()); final Event updatedEvent = eventRepository.findById(eventId).get(); //then @@ -325,7 +358,7 @@ void updateEventWithNotExistsEventTest() { //when & then final EventException exception = assertThrowsExactly(EventException.class, () -> eventCommandService.updateEvent(notExistsEventId, updateRequest, - mockMultipartFiles)); + mockMultipartFiles, adminMember())); assertEquals(NOT_FOUND_EVENT, exception.exceptionType()); } @@ -357,7 +390,8 @@ void updateEventWithStartDateTimeAfterBeforeDateTimeTest() { //when & then final EventException exception = assertThrowsExactly(EventException.class, - () -> eventCommandService.updateEvent(eventId, updateRequest, mockMultipartFiles)); + () -> eventCommandService.updateEvent(eventId, updateRequest, mockMultipartFiles, + adminMember())); assertEquals(START_DATE_TIME_AFTER_END_DATE_TIME, exception.exceptionType()); } @@ -390,10 +424,41 @@ void updateEventWithNotExistTagTest() { //when & then final EventException exception = assertThrowsExactly(EventException.class, - () -> eventCommandService.updateEvent(eventId, updateRequest, mockMultipartFiles)); + () -> eventCommandService.updateEvent(eventId, updateRequest, mockMultipartFiles, + adminMember())); assertEquals(NOT_FOUND_TAG, exception.exceptionType()); } + + @Test + @DisplayName("관리자가 아닌 회원이 행사를 수정할 경우 LoginException이 발생한다.") + void updateEvent_fail_authorization() { + //given + final EventDetailRequest updateRequest = new EventDetailRequest( + newName, + newLocation, + newInformationUrl, + beforeDateTime, + afterDateTime, + beforeDateTime, + afterDateTime, + newTagRequests, + EventType.CONFERENCE, + eventMode, + paymentType, + organization + ); + + final Event event = eventRepository.save(인프콘_2023()); + final Long eventId = event.getId(); + + //when & then + final LoginException exception = assertThrowsExactly(LoginException.class, + () -> eventCommandService.updateEvent(eventId, updateRequest, mockMultipartFiles, + generalMember())); + + assertEquals(INVALID_ACCESS_TOKEN, exception.exceptionType()); + } } @Nested @@ -407,7 +472,7 @@ void deleteEventTest() { final Long eventId = event.getId(); //when - eventCommandService.deleteEvent(eventId); + eventCommandService.deleteEvent(eventId, adminMember()); //then assertFalse(eventRepository.findById(eventId).isPresent()); @@ -421,10 +486,24 @@ void deleteEventWithNotExistsEventTest() { //when & then final EventException exception = assertThrowsExactly(EventException.class, - () -> eventCommandService.deleteEvent(notExistsEventId)); + () -> eventCommandService.deleteEvent(notExistsEventId, adminMember())); assertEquals(NOT_FOUND_EVENT, exception.exceptionType()); } + + @Test + @DisplayName("관지자가 아닌 회원이 행사를 삭제할 경우 LoginException이 발생한다.") + void deleteEvent_fail_authorization() { + //given + final Event event = eventRepository.save(인프콘_2023()); + final Long eventId = event.getId(); + + //when & then + final LoginException exception = assertThrowsExactly(LoginException.class, + () -> eventCommandService.deleteEvent(eventId, generalMember())); + + assertEquals(INVALID_ACCESS_TOKEN, exception.exceptionType()); + } } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java index 7a5e48cf6..d88606ec0 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventServiceEventIntegrationTestQuery.java @@ -1,5 +1,6 @@ package com.emmsale.admin.event.application; +import static com.emmsale.member.MemberFixture.adminMember; import static com.emmsale.tag.TagFixture.IOS; import static com.emmsale.tag.TagFixture.백엔드; import static com.emmsale.tag.TagFixture.안드로이드; @@ -77,7 +78,7 @@ void test_publish_event() throws Exception { ); //when - eventCommandService.addEvent(eventDetailRequest, null); + eventCommandService.addEvent(eventDetailRequest, null, adminMember()); //then verify(firebaseCloudMessageClient, times(2)) @@ -121,7 +122,7 @@ void test_publish_event_no_notification_event_has_no_interest_tag() throws Excep ); //when - eventCommandService.addEvent(eventDetailRequest, null); + eventCommandService.addEvent(eventDetailRequest, null, adminMember()); //then verify(firebaseCloudMessageClient, times(0)) @@ -155,7 +156,7 @@ void test_publish_event_no_notification_member_has_no_interest_tag() throws Exce ); //when - eventCommandService.addEvent(eventDetailRequest, null); + eventCommandService.addEvent(eventDetailRequest, null, adminMember()); //then verify(firebaseCloudMessageClient, times(0)) diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java index 4de6768f2..a30e38cd0 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java @@ -2,6 +2,9 @@ import static com.emmsale.event.EventFixture.eventFixture; +import static com.emmsale.member.MemberFixture.adminMember; +import static com.emmsale.member.MemberFixture.generalMember; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.emmsale.comment.domain.Comment; import com.emmsale.comment.domain.CommentRepository; @@ -10,6 +13,8 @@ import com.emmsale.feed.domain.Feed; import com.emmsale.feed.domain.repository.FeedRepository; import com.emmsale.helper.ServiceIntegrationTestHelper; +import com.emmsale.login.exception.LoginException; +import com.emmsale.login.exception.LoginExceptionType; import com.emmsale.member.domain.Member; import com.emmsale.member.domain.MemberRepository; import com.emmsale.report.application.ReportCommandService; @@ -19,6 +24,7 @@ import com.emmsale.report.domain.ReportType; import java.util.List; import org.assertj.core.api.Assertions; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -69,13 +75,24 @@ void findReports() { report.getType(), report.getContentId(), report.getCreatedAt())); // when - final List actual = reportQueryService.findReports(); + final List actual = reportQueryService.findReports(adminMember()); // then Assertions.assertThat(actual) .usingRecursiveComparison() .ignoringFields("createdAt") .isEqualTo(expected); + } + + @Test + @DisplayName("관리자가 아닌 회원이 신고 목록을 조회하면 예외를 반환한다.") + void findReports_fail_authorization() { + // given, when + final ThrowingCallable actual = () -> reportQueryService.findReports(generalMember()); + // then + assertThatThrownBy(actual) + .isInstanceOf(LoginException.class) + .hasMessage(LoginExceptionType.INVALID_ACCESS_TOKEN.errorMessage()); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java index 4fdd936d6..b64e3079c 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java @@ -1,9 +1,13 @@ package com.emmsale.admin.tag.application; +import static com.emmsale.member.MemberFixture.adminMember; +import static com.emmsale.member.MemberFixture.generalMember; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import com.emmsale.helper.ServiceIntegrationTestHelper; +import com.emmsale.login.exception.LoginException; +import com.emmsale.login.exception.LoginExceptionType; import com.emmsale.tag.application.dto.TagRequest; import com.emmsale.tag.application.dto.TagResponse; import com.emmsale.tag.exception.TagException; @@ -27,7 +31,7 @@ void findAll() { final TagResponse expected = new TagResponse(1L, tagName); //when - final TagResponse actual = commandService.addTag(request); + final TagResponse actual = commandService.addTag(request, adminMember()); //then assertThat(actual) @@ -37,14 +41,14 @@ void findAll() { @Test @DisplayName("이미 존재하는 태그를 추가하면 예외를 반환한다.") - void addTag_duplicate_fail() { + void addTag_fail_duplicate() { //given final String tagName = "프론트엔드"; final TagRequest request = new TagRequest(tagName); - commandService.addTag(request); + commandService.addTag(request, adminMember()); //when - final ThrowingCallable actual = () -> commandService.addTag(request); + final ThrowingCallable actual = () -> commandService.addTag(request, adminMember()); //then assertThatThrownBy(actual) @@ -52,5 +56,19 @@ void addTag_duplicate_fail() { .hasMessage(TagExceptionType.ALEADY_EXIST_TAG.errorMessage()); } + @Test + @DisplayName("관리자가 아닌 회원이 태그를 추가하면 예외를 반환한다.") + void addTag_fail_authorization() { + //given + final String tagName = "프론트엔드"; + final TagRequest request = new TagRequest(tagName); + //when + final ThrowingCallable actual = () -> commandService.addTag(request, generalMember()); + + //then + assertThatThrownBy(actual) + .isInstanceOf(LoginException.class) + .hasMessage(LoginExceptionType.INVALID_ACCESS_TOKEN.errorMessage()); + } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/member/MemberFixture.java b/backend/emm-sale/src/test/java/com/emmsale/member/MemberFixture.java index b6520bb38..7e969a425 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/member/MemberFixture.java +++ b/backend/emm-sale/src/test/java/com/emmsale/member/MemberFixture.java @@ -5,8 +5,7 @@ public class MemberFixture { public static Member memberFixture() { - final Member member = new Member( - 1234L, + final Member member = new Member(1234L, "https://avatars.githubusercontent.com/0/4", "아마란스" ); @@ -14,6 +13,29 @@ public static Member memberFixture() { return member; } + public static Member generalMember() { + final Member member = new Member(1L, + 1234L, + "https://avatars.githubusercontent.com/0/4", + "아마란스", + "amaran-th" + ); + member.updateName("우르"); + return member; + } + + public static Member adminMember() { + final long adminMemberId = 3L; + final Member member = new Member(adminMemberId, + 1234L, + "https://avatars.githubusercontent.com/0/4", + "아마란스", + "amaran-th" + ); + member.updateName("관리자"); + return member; + } + public static Member create( final Long githubId, final String githubUsername, From 84b549332bbd21149de895b7a79b86aeea4b15b2 Mon Sep 17 00:00:00 2001 From: amaran-th Date: Fri, 24 Nov 2023 20:34:02 +0900 Subject: [PATCH 04/20] =?UTF-8?q?feat:=20dev=20application.yml=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=82=AC=ED=95=AD=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156 --- backend/emm-sale/src/main/resources/kerdy-submodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/emm-sale/src/main/resources/kerdy-submodule b/backend/emm-sale/src/main/resources/kerdy-submodule index 201498016..acf74aa02 160000 --- a/backend/emm-sale/src/main/resources/kerdy-submodule +++ b/backend/emm-sale/src/main/resources/kerdy-submodule @@ -1 +1 @@ -Subproject commit 201498016c6f27f34972c92cf1699252e294033b +Subproject commit acf74aa027b240d61a3b0ea6767c44822c0bad25 From 2d56921cf97db575159040887e4051b42c62439e Mon Sep 17 00:00:00 2001 From: amaran-th Date: Mon, 27 Nov 2023 14:48:58 +0900 Subject: [PATCH 05/20] =?UTF-8?q?feat:=20prod=20application.yml=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156 --- backend/emm-sale/src/main/resources/kerdy-submodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/emm-sale/src/main/resources/kerdy-submodule b/backend/emm-sale/src/main/resources/kerdy-submodule index acf74aa02..b741a5d8d 160000 --- a/backend/emm-sale/src/main/resources/kerdy-submodule +++ b/backend/emm-sale/src/main/resources/kerdy-submodule @@ -1 +1 @@ -Subproject commit acf74aa027b240d61a3b0ea6767c44822c0bad25 +Subproject commit b741a5d8d4bf78caa57b307d75ab7a7918f4e13e From 98c5c3dcdc874ba45c7b11fd4c2719727157d0d1 Mon Sep 17 00:00:00 2001 From: amaran-th Date: Mon, 27 Nov 2023 15:08:58 +0900 Subject: [PATCH 06/20] =?UTF-8?q?feat:=20=ED=8C=8C=EC=9D=BC=20=EB=A7=88?= =?UTF-8?q?=EC=A7=80=EB=A7=89=20=EC=A4=84=EC=97=90=20=EB=B9=88=20=EC=A4=84?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156 --- .../emmsale/admin/login/application/AdminLoginServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java index 52aaffed0..d3c280b3a 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java @@ -97,4 +97,4 @@ void createAdminToken_fail_invalid_password() { .hasMessage(expectExceptionType.errorMessage()); } -} \ No newline at end of file +} From 9d2a118340cb846a0599ee59289bf0873dd0f9ec Mon Sep 17 00:00:00 2001 From: amaran-th Date: Mon, 27 Nov 2023 17:29:29 +0900 Subject: [PATCH 07/20] =?UTF-8?q?refactor:=20dto=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EC=97=90=20private=20=EC=A0=91=EA=B7=BC=20=EC=A0=9C=EC=96=B4?= =?UTF-8?q?=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156 --- .../admin/login/application/dto/AdminLoginRequest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java index 54706ff2b..ed02c9ece 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/application/dto/AdminLoginRequest.java @@ -7,7 +7,7 @@ @RequiredArgsConstructor public class AdminLoginRequest { - final String id; - final String password; + private final String id; + private final String password; } From 2f2de41c1645007be6ac06448197f84d6473f8f7 Mon Sep 17 00:00:00 2001 From: amaran-th Date: Mon, 27 Nov 2023 20:37:10 +0900 Subject: [PATCH 08/20] =?UTF-8?q?refactor:=20@Mockbean=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20ServiceIntegrationTestHelper=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156 --- .../src/documentTest/java/com/emmsale/EventApiTest.java | 8 +++++--- .../admin/login/application/AdminLoginServiceTest.java | 4 ---- .../com/emmsale/helper/ServiceIntegrationTestHelper.java | 3 +++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java index 0ed7356ec..aeab6a1c3 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java @@ -52,6 +52,7 @@ import org.springframework.restdocs.request.RequestParametersSnippet; import org.springframework.restdocs.request.RequestPartsSnippet; import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; @@ -264,14 +265,15 @@ void updateEventTest() throws Exception { ); //when - final MockMultipartHttpServletRequestBuilder builder = multipart(HttpMethod.PUT, + final MockHttpServletRequestBuilder builder = multipart(HttpMethod.PUT, "/admin/events/" + eventId) .file("images", image1.getBytes()) .file("images", image2.getBytes()) .file(new MockMultipartFile("request", "", "application/json", contents.getBytes( - StandardCharsets.UTF_8))); + StandardCharsets.UTF_8))) + .header("Authorization", accessToken); - final ResultActions result = mockMvc.perform(builder.header("Authorization", accessToken)); + final ResultActions result = mockMvc.perform(builder); //when & then result.andExpect(status().isOk()) diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java index d3c280b3a..06ba7e791 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java @@ -8,7 +8,6 @@ import com.emmsale.helper.ServiceIntegrationTestHelper; import com.emmsale.login.exception.LoginException; import com.emmsale.login.exception.LoginExceptionType; -import com.emmsale.login.utils.JwtTokenProvider; import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; @@ -16,15 +15,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; @SpringBootTest class AdminLoginServiceTest extends ServiceIntegrationTestHelper { @Autowired private AdminLoginService adminLoginService; - @MockBean - private JwtTokenProvider tokenProvider; @Value("${data.admin_login.id}") private String adminId; @Value("${data.admin_login.password}") diff --git a/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java b/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java index 1d91a4475..18d6093e8 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java +++ b/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java @@ -3,6 +3,7 @@ import com.emmsale.image.application.ImageCommandService; import com.emmsale.image.application.S3Client; import com.emmsale.login.utils.GithubClient; +import com.emmsale.login.utils.JwtTokenProvider; import com.emmsale.notification.application.FirebaseCloudMessageClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -20,5 +21,7 @@ public abstract class ServiceIntegrationTestHelper { @MockBean protected ImageCommandService imageCommandService; @MockBean + protected JwtTokenProvider tokenProvider; + @MockBean protected S3Client s3Client; } From 27bb2aac9dc25cf9e8d275880c053f2a0d19eeda Mon Sep 17 00:00:00 2001 From: amaran-th Date: Tue, 28 Nov 2023 11:55:14 +0900 Subject: [PATCH 09/20] =?UTF-8?q?refactor:=20=EA=B4=80=EB=A6=AC=EC=9E=90?= =?UTF-8?q?=20=ED=86=A0=ED=81=B0=20=EA=B2=80=EC=A6=9D=20=EC=8B=A4=ED=8C=A8?= =?UTF-8?q?=20=EC=8B=9C=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=9C=A0=ED=98=95=EC=9D=84=20INVALID=5FADMIN=5FACC?= =?UTF-8?q?ESS=5FTOKEN=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156 --- .../com/emmsale/admin/login/utils/AdminValidator.java | 2 +- .../activity/application/ActivityCommandServiceTest.java | 2 +- .../admin/event/application/EventCommandServiceTest.java | 8 ++++---- .../admin/report/application/ReportQueryServiceTest.java | 2 +- .../admin/tag/application/TagCommandServiceTest.java | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java b/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java index fa58c5457..6ae80eb7d 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java +++ b/backend/emm-sale/src/main/java/com/emmsale/admin/login/utils/AdminValidator.java @@ -13,7 +13,7 @@ public class AdminValidator { public static void validateAuthorization(final Member admin) { if (admin.isNotMe(adminMemberId)) { - throw new LoginException(LoginExceptionType.INVALID_ACCESS_TOKEN); + throw new LoginException(LoginExceptionType.INVALID_ADMIN_ACCESS_TOKEN); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java index c44beb9b4..7946259b2 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/activity/application/ActivityCommandServiceTest.java @@ -77,6 +77,6 @@ void findActivity_fail_authorization() { //then assertThatThrownBy(actual) .isInstanceOf(LoginException.class) - .hasMessage(LoginExceptionType.INVALID_ACCESS_TOKEN.errorMessage()); + .hasMessage(LoginExceptionType.INVALID_ADMIN_ACCESS_TOKEN.errorMessage()); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java index 85bed8fbe..b611a1497 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java @@ -11,7 +11,7 @@ import static com.emmsale.image.ImageFixture.행사_이미지1; import static com.emmsale.image.ImageFixture.행사_이미지2; import static com.emmsale.image.ImageFixture.행사_이미지3; -import static com.emmsale.login.exception.LoginExceptionType.INVALID_ACCESS_TOKEN; +import static com.emmsale.login.exception.LoginExceptionType.INVALID_ADMIN_ACCESS_TOKEN; import static com.emmsale.member.MemberFixture.adminMember; import static com.emmsale.member.MemberFixture.generalMember; import static com.emmsale.tag.TagFixture.AI; @@ -268,7 +268,7 @@ void addEvent_fail_authorization() { final LoginException exception = assertThrowsExactly(LoginException.class, () -> eventCommandService.addEvent(request, mockMultipartFiles, generalMember())); - assertEquals(INVALID_ACCESS_TOKEN, exception.exceptionType()); + assertEquals(INVALID_ADMIN_ACCESS_TOKEN, exception.exceptionType()); } } @@ -457,7 +457,7 @@ void updateEvent_fail_authorization() { () -> eventCommandService.updateEvent(eventId, updateRequest, mockMultipartFiles, generalMember())); - assertEquals(INVALID_ACCESS_TOKEN, exception.exceptionType()); + assertEquals(INVALID_ADMIN_ACCESS_TOKEN, exception.exceptionType()); } } @@ -502,7 +502,7 @@ void deleteEvent_fail_authorization() { final LoginException exception = assertThrowsExactly(LoginException.class, () -> eventCommandService.deleteEvent(eventId, generalMember())); - assertEquals(INVALID_ACCESS_TOKEN, exception.exceptionType()); + assertEquals(INVALID_ADMIN_ACCESS_TOKEN, exception.exceptionType()); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java index a30e38cd0..37af75f8f 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/report/application/ReportQueryServiceTest.java @@ -93,6 +93,6 @@ void findReports_fail_authorization() { // then assertThatThrownBy(actual) .isInstanceOf(LoginException.class) - .hasMessage(LoginExceptionType.INVALID_ACCESS_TOKEN.errorMessage()); + .hasMessage(LoginExceptionType.INVALID_ADMIN_ACCESS_TOKEN.errorMessage()); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java index b64e3079c..bcc2d045d 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/tag/application/TagCommandServiceTest.java @@ -69,6 +69,6 @@ void addTag_fail_authorization() { //then assertThatThrownBy(actual) .isInstanceOf(LoginException.class) - .hasMessage(LoginExceptionType.INVALID_ACCESS_TOKEN.errorMessage()); + .hasMessage(LoginExceptionType.INVALID_ADMIN_ACCESS_TOKEN.errorMessage()); } } From 5160b4181e808614b3b4f347afec7ec134960c82 Mon Sep 17 00:00:00 2001 From: amaran-th Date: Tue, 28 Nov 2023 12:26:20 +0900 Subject: [PATCH 10/20] =?UTF-8?q?refactor:=20JwtTokenProvider=EB=A5=BC=20M?= =?UTF-8?q?ocking=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=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 #156 --- .../admin/login/application/AdminLoginServiceTest.java | 7 ++++--- .../com/emmsale/helper/ServiceIntegrationTestHelper.java | 3 --- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java index 06ba7e791..c28049f9c 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/login/application/AdminLoginServiceTest.java @@ -1,13 +1,13 @@ package com.emmsale.admin.login.application; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.BDDMockito.given; import com.emmsale.admin.login.application.dto.AdminLoginRequest; import com.emmsale.admin.login.application.dto.AdminTokenResponse; import com.emmsale.helper.ServiceIntegrationTestHelper; import com.emmsale.login.exception.LoginException; import com.emmsale.login.exception.LoginExceptionType; +import com.emmsale.login.utils.JwtTokenProvider; import org.assertj.core.api.Assertions; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DisplayName; @@ -19,6 +19,8 @@ @SpringBootTest class AdminLoginServiceTest extends ServiceIntegrationTestHelper { + @Autowired + private JwtTokenProvider jwtTokenProvider; @Autowired private AdminLoginService adminLoginService; @Value("${data.admin_login.id}") @@ -34,8 +36,7 @@ void createAdminToken_success() { // given final Long memberId = adminMemberId; final AdminLoginRequest request = new AdminLoginRequest(adminId, adminPassword); - final String expectAccessToken = "expect_access_token"; - given(tokenProvider.createToken(String.valueOf(memberId))).willReturn(expectAccessToken); + final String expectAccessToken = jwtTokenProvider.createToken(String.valueOf(memberId)); // when final AdminTokenResponse actualToken = adminLoginService.createAdminToken(request); diff --git a/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java b/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java index 18d6093e8..1d91a4475 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java +++ b/backend/emm-sale/src/test/java/com/emmsale/helper/ServiceIntegrationTestHelper.java @@ -3,7 +3,6 @@ import com.emmsale.image.application.ImageCommandService; import com.emmsale.image.application.S3Client; import com.emmsale.login.utils.GithubClient; -import com.emmsale.login.utils.JwtTokenProvider; import com.emmsale.notification.application.FirebaseCloudMessageClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -21,7 +20,5 @@ public abstract class ServiceIntegrationTestHelper { @MockBean protected ImageCommandService imageCommandService; @MockBean - protected JwtTokenProvider tokenProvider; - @MockBean protected S3Client s3Client; } From 342c75274262ba963c36b0850c378ad8ab8c0368 Mon Sep 17 00:00:00 2001 From: hong-sile Date: Tue, 28 Nov 2023 14:55:43 +0900 Subject: [PATCH 11/20] =?UTF-8?q?feat:=20=EC=84=9C=EB=B8=8C=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/emm-sale/src/main/resources/kerdy-submodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/emm-sale/src/main/resources/kerdy-submodule b/backend/emm-sale/src/main/resources/kerdy-submodule index 0de927e9c..b741a5d8d 160000 --- a/backend/emm-sale/src/main/resources/kerdy-submodule +++ b/backend/emm-sale/src/main/resources/kerdy-submodule @@ -1 +1 @@ -Subproject commit 0de927e9c8f427883b94f9d72a51f7879e0fca10 +Subproject commit b741a5d8d4bf78caa57b307d75ab7a7918f4e13e From b07ab3193f00d6c3af94e8bd7c7d959024c64f73 Mon Sep 17 00:00:00 2001 From: hong-sile Date: Fri, 1 Dec 2023 20:16:32 +0900 Subject: [PATCH 12/20] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20400=EC=9D=B4=20=EC=95=84=EB=8B=8C=20401=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -864 --- .../java/com/emmsale/login/exception/LoginExceptionType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java b/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java index c51365b7f..a2b38f375 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java +++ b/backend/emm-sale/src/main/java/com/emmsale/login/exception/LoginExceptionType.java @@ -14,7 +14,7 @@ public enum LoginExceptionType implements BaseExceptionType { "GitHub Profile을 찾을 수 없습니다." ), INVALID_ACCESS_TOKEN( - HttpStatus.BAD_REQUEST, + HttpStatus.UNAUTHORIZED, "토큰이 유효하지 않습니다." ), NOT_FOUND_AUTHORIZATION_TOKEN( From c915b069fd847a2acaee0641a085222cf7b7071d Mon Sep 17 00:00:00 2001 From: hong-sile Date: Sat, 13 Jan 2024 02:33:58 +0900 Subject: [PATCH 13/20] =?UTF-8?q?feat:=20Event=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EventAPI Test 코드 수정 - EventResponse에 TagResponse가 포함되도록 리팩터링 #893 --- .../java/com/emmsale/EventApiTest.java | 20 +++++++++++++------ .../event/application/dto/EventResponse.java | 10 +++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java index aeab6a1c3..c7dc6e9f2 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/EventApiTest.java @@ -24,6 +24,7 @@ import com.emmsale.member.domain.Member; import com.emmsale.tag.TagFixture; import com.emmsale.tag.application.dto.TagRequest; +import com.emmsale.tag.application.dto.TagResponse; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.HashMap; @@ -76,6 +77,8 @@ class EventApiTest extends MockMvcTestHelper { .description("신청 종료일자(nullable)"), fieldWithPath("location").type(JsonFieldType.STRING).description("장소"), fieldWithPath("tags[]").type(JsonFieldType.ARRAY).description("태그들"), + fieldWithPath("tags[].id").type(JsonFieldType.NUMBER).description("행사 태그 ID"), + fieldWithPath("tags[].name").type(JsonFieldType.STRING).description("행사 태그 이름"), fieldWithPath("thumbnailUrl").type(JsonFieldType.STRING) .description("섬네일 이미지 Url(포스터)"), fieldWithPath("type").type(JsonFieldType.STRING) @@ -100,7 +103,9 @@ class EventApiTest extends MockMvcTestHelper { fieldWithPath("[].applyEndDate").type(JsonFieldType.STRING) .description("행사 신청 종료 일자(nullable)"), fieldWithPath("[].location").type(JsonFieldType.STRING).description("행사 장소"), - fieldWithPath("[].tags[]").type(JsonFieldType.ARRAY).description("행사 태그들"), + fieldWithPath("[].tags[]").type(JsonFieldType.ARRAY).description("태그들"), + fieldWithPath("[].tags[].id").type(JsonFieldType.NUMBER).description("행사 태그 ID"), + fieldWithPath("[].tags[].name").type(JsonFieldType.STRING).description("행사 태그 이름"), fieldWithPath("[].thumbnailUrl").type(JsonFieldType.STRING) .description("행사 섬네일 이미지 Url(포스터)"), fieldWithPath("[].type").type(JsonFieldType.STRING) @@ -116,11 +121,14 @@ class EventApiTest extends MockMvcTestHelper { void findEvent() throws Exception { //given final Long eventId = 1L; + final List tagResponses = List.of( + new TagResponse(1L, "코틀린"), new TagResponse(2L, "백엔드"), new TagResponse(3L, "안드로이드") + ); final EventResponse eventResponse = new EventResponse(eventId, "인프콘 2023", "http://infcon.com", LocalDateTime.of(2023, 8, 15, 12, 0), LocalDateTime.of(2023, 8, 15, 12, 0), LocalDateTime.of(2023, 8, 1, 12, 0), LocalDateTime.of(2023, 8, 15, 12, 0), "코엑스", - List.of("코틀린", "백엔드", "안드로이드"), + tagResponses, "https://www.image.com", EventType.COMPETITION.toString(), List.of("imageUrl1", "imageUrl2"), "인프런", "유료", "온라인"); @@ -163,7 +171,7 @@ void findEvents() throws Exception { LocalDateTime.parse("2023-08-03T12:00:00"), LocalDateTime.parse("2023-06-23T10:00:00"), LocalDateTime.parse("2023-07-03T12:00:00"), - "코엑스", List.of("백엔드", "프론트엔드"), + "코엑스", List.of(new TagResponse(1L, "백엔드"), new TagResponse(2L, "프론트엔드")), "imageUrl0", EventType.CONFERENCE.name(), List.of("imageUrl1", "imageUrl2"), "인프런", PaymentType.PAID.getValue(), @@ -175,7 +183,7 @@ void findEvents() throws Exception { LocalDateTime.parse("2023-07-30T12:00:00"), LocalDateTime.parse("2023-07-01T00:00:00"), LocalDateTime.parse("2023-07-21T23:59:59"), - "코엑스", List.of("AI"), + "코엑스", List.of(new TagResponse(5L, "AI")), "imageUrl0", EventType.CONFERENCE.name(), List.of("imageUrl1", "imageUrl2"), "인프런", PaymentType.PAID.getValue(), @@ -234,7 +242,7 @@ void updateEventTest() throws Exception { request.getInformationUrl(), request.getStartDateTime(), request.getEndDateTime(), request.getApplyStartDateTime(), request.getApplyEndDateTime(), request.getLocation(), - tags.stream().map(TagRequest::getName).collect(Collectors.toList()), + List.of(new TagResponse(1L, "백엔드"), new TagResponse(2L, "안드로이드")), "image1.jpg", request.getType().toString(), List.of("imageUrl1", "imageUrl2"), "행사기관", "유료", "온라인"); @@ -339,7 +347,7 @@ void addEventTest() throws Exception { request.getInformationUrl(), request.getStartDateTime(), request.getEndDateTime(), request.getApplyStartDateTime(), request.getApplyEndDateTime(), request.getLocation(), - tags.stream().map(TagRequest::getName).collect(Collectors.toList()), + List.of(new TagResponse(1L, "백엔드"), new TagResponse(2L, "안드로이드")), "image1.jpg", request.getType().toString(), List.of("imageUrl1", "imageUrl2"), "행사기관", "무료", "오프라인"); diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/EventResponse.java b/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/EventResponse.java index de14d8ab3..e4cfed34b 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/EventResponse.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/EventResponse.java @@ -6,7 +6,7 @@ import com.emmsale.event.domain.EventStatus; import com.emmsale.event.domain.EventTag; import com.emmsale.image.domain.AllImagesOfContent; -import com.emmsale.tag.domain.Tag; +import com.emmsale.tag.application.dto.TagResponse; import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; import java.util.ArrayList; @@ -34,7 +34,7 @@ public class EventResponse { @JsonFormat(pattern = DATE_TIME_FORMAT) private final LocalDateTime applyEndDate; private final String location; - private final List tags; + private final List tags; private final String thumbnailUrl; private final String type; private final List imageUrls; @@ -46,9 +46,9 @@ public static EventResponse from( final Event event, final AllImagesOfContent images ) { - final List tagNames = event.getTags().stream() + final List tagResponses = event.getTags().stream() .map(EventTag::getTag) - .map(Tag::getName) + .map(TagResponse::from) .collect(toUnmodifiableList()); return new EventResponse( @@ -60,7 +60,7 @@ public static EventResponse from( event.getEventPeriod().getApplyStartDate(), event.getEventPeriod().getApplyEndDate(), event.getLocation(), - tagNames, + tagResponses, images.extractThumbnailImage(), event.getType().toString(), images.extractInformationImages(), From 972a8fa546910fd0d81f2c2f6aed05e3971e524b Mon Sep 17 00:00:00 2001 From: hong-sile Date: Sat, 13 Jan 2024 02:36:27 +0900 Subject: [PATCH 14/20] =?UTF-8?q?test:=20scrapAPITest=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #893 --- .../java/com/emmsale/ScrapApiTest.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/ScrapApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/ScrapApiTest.java index 9b7d2d5bb..3aa7a4059 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/ScrapApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/ScrapApiTest.java @@ -16,6 +16,7 @@ import com.emmsale.event.domain.PaymentType; import com.emmsale.scrap.api.ScrapApi; import com.emmsale.scrap.application.dto.ScrapRequest; +import com.emmsale.tag.application.dto.TagResponse; import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -31,7 +32,13 @@ @WebMvcTest(ScrapApi.class) class ScrapApiTest extends MockMvcTestHelper { - final ResponseFieldsSnippet SCRAPPED_EVENT_RESPONSE_FIELDS = PayloadDocumentation.responseFields( + private static final List TAG_RESPONSES = List.of( + new TagResponse(1L, "백엔드"), new TagResponse(2L, "프론트엔드"), + new TagResponse(3L, "안드로이드"), new TagResponse(4L, "IOS"), + new TagResponse(5L, "AI") + ); + + static final ResponseFieldsSnippet SCRAPPED_EVENT_RESPONSE_FIELDS = PayloadDocumentation.responseFields( fieldWithPath("id").type(JsonFieldType.NUMBER).description("행사 식별자"), fieldWithPath("name").type(JsonFieldType.STRING) .description("행사 이름"), @@ -45,7 +52,9 @@ class ScrapApiTest extends MockMvcTestHelper { fieldWithPath("applyEndDate").type(JsonFieldType.STRING) .description("행사 신청 종료 일자(nullable)"), fieldWithPath("location").type(JsonFieldType.STRING).description("행사 장소"), - fieldWithPath("tags[]").type(JsonFieldType.ARRAY).description("행사 태그들"), + fieldWithPath("tags[]").type(JsonFieldType.ARRAY).description("태그들"), + fieldWithPath("tags[].id").type(JsonFieldType.NUMBER).description("행사 태그 ID"), + fieldWithPath("tags[].name").type(JsonFieldType.STRING).description("행사 태그 이름"), fieldWithPath("thumbnailUrl").type(JsonFieldType.STRING) .description("행사 섬네일 이미지 Url(포스터)"), fieldWithPath("type").type(JsonFieldType.STRING) @@ -70,7 +79,7 @@ void findAllScraps() throws Exception { LocalDateTime.parse("2023-09-01T00:00:00"), LocalDateTime.parse("2023-09-02T23:59:59"), "코엑스", - List.of("백엔드", "프론트엔드", "안드로이드", "IOS", "AI"), + TAG_RESPONSES, "image0.jpg", EventType.CONFERENCE.name(), List.of("image1.jpg", "image2.jpg", "image3.jpg"), @@ -87,7 +96,7 @@ void findAllScraps() throws Exception { LocalDateTime.parse("2023-09-01T00:00:00"), LocalDateTime.parse("2023-09-02T23:59:59"), "코엑스", - List.of("백엔드", "프론트엔드", "안드로이드", "IOS", "AI"), + TAG_RESPONSES, "image0.jpg", EventType.CONFERENCE.name(), List.of("image1.jpg", "image2.jpg", "image3.jpg"), @@ -102,7 +111,7 @@ void findAllScraps() throws Exception { LocalDateTime.parse("2023-09-01T00:00:00"), LocalDateTime.parse("2023-09-02T23:59:59"), "코엑스", - List.of("백엔드", "프론트엔드", "안드로이드", "IOS", "AI"), + TAG_RESPONSES, "image0.jpg", EventType.CONFERENCE.name(), List.of("image1.jpg", "image2.jpg", "image3.jpg"), @@ -125,7 +134,9 @@ void findAllScraps() throws Exception { fieldWithPath("[].applyEndDate").type(JsonFieldType.STRING) .description("행사 신청 종료 일자(nullable)"), fieldWithPath("[].location").type(JsonFieldType.STRING).description("행사 장소"), - fieldWithPath("[].tags[]").type(JsonFieldType.ARRAY).description("행사 태그들"), + fieldWithPath("[].tags[]").type(JsonFieldType.ARRAY).description("태그들"), + fieldWithPath("[].tags[].id").type(JsonFieldType.NUMBER).description("행사 태그 ID"), + fieldWithPath("[].tags[].name").type(JsonFieldType.STRING).description("행사 태그 이름"), fieldWithPath("[].thumbnailUrl").type(JsonFieldType.STRING) .description("행사 섬네일 이미지 Url(포스터)"), fieldWithPath("[].type").type(JsonFieldType.STRING) @@ -161,7 +172,7 @@ void append() throws Exception { LocalDateTime.parse("2023-09-01T00:00:00"), LocalDateTime.parse("2023-09-02T23:59:59"), "코엑스", - List.of("백엔드", "프론트엔드", "안드로이드", "IOS", "AI"), + TAG_RESPONSES, "image0.jpg", EventType.CONFERENCE.name(), List.of("image1.jpg", "image2.jpg", "image3.jpg"), @@ -199,7 +210,7 @@ void deleteScrap() throws Exception { LocalDateTime.parse("2023-09-01T00:00:00"), LocalDateTime.parse("2023-09-02T23:59:59"), "코엑스", - List.of("백엔드", "프론트엔드", "안드로이드", "IOS", "AI"), + TAG_RESPONSES, "image0.jpg", EventType.CONFERENCE.name(), List.of("image1.jpg", "image2.jpg", "image3.jpg"), From 60e8b7201aff5959ebbff997cbf02e28e86e703f Mon Sep 17 00:00:00 2001 From: hong-sile Date: Sat, 13 Jan 2024 02:49:49 +0900 Subject: [PATCH 15/20] =?UTF-8?q?test:=20service=EC=97=90=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=93=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #893 --- .../application/EventCommandServiceTest.java | 6 ++++-- .../application/EventQueryServiceTest.java | 21 +++++++++++-------- .../application/ScrapQueryServiceTest.java | 6 +++--- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java index b611a1497..4d548ae6f 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java @@ -168,7 +168,8 @@ void addEventTest() { () -> assertEquals(afterDateTime, savedEvent.getEventPeriod().getEndDate()) ); assertThat(response.getTags()) - .containsAll( + .extracting("name") + .containsExactlyInAnyOrder( tagRequests.stream() .map(TagRequest::getName) .collect(Collectors.toList()) @@ -327,7 +328,8 @@ void updateEventTest() { () -> assertEquals(newInformationUrl, updatedEvent.getInformationUrl()) ); assertThat(response.getTags()) - .containsAll( + .extracting("name") + .containsExactlyInAnyOrder( newTagRequests.stream() .map(TagRequest::getName) .collect(Collectors.toList()) diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventQueryServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/event/application/EventQueryServiceTest.java index 121cf9ffe..dd12b45b5 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/event/application/EventQueryServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/event/application/EventQueryServiceTest.java @@ -39,6 +39,7 @@ import com.emmsale.image.domain.Image; import com.emmsale.image.domain.ImageType; import com.emmsale.image.domain.repository.ImageRepository; +import com.emmsale.tag.application.dto.TagResponse; import com.emmsale.tag.domain.Tag; import com.emmsale.tag.domain.TagRepository; import com.emmsale.tag.exception.TagException; @@ -58,32 +59,33 @@ class EventQueryServiceTest extends ServiceIntegrationTestHelper { + private static final TagResponse 백엔드 = new TagResponse(1L, "백엔드"); private static final EventResponse 인프콘_2023 = new EventResponse(null, "인프콘 2023", - null, null, null, null, null, "코엑스", List.of("백엔드"), + null, null, null, null, null, "코엑스", List.of(백엔드), "이미지1", EventType.CONFERENCE.name(), List.of(), "인프런", PaymentType.PAID.getValue(), EventMode.OFFLINE.getValue()); private static final EventResponse 웹_컨퍼런스 = new EventResponse(null, "웹 컨퍼런스", null, null, null, - null, null, "코엑스", List.of("백엔드"), "이미지1", EventType.CONFERENCE.name(), + null, null, "코엑스", List.of(백엔드), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); private static final EventResponse 안드로이드_컨퍼런스 = new EventResponse(null, "안드로이드 컨퍼런스", - null, null, null, null, null, "코엑스", List.of("백엔드"), + null, null, null, null, null, "코엑스", List.of(백엔드), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); private static final EventResponse AI_컨퍼런스 = new EventResponse(null, "AI 컨퍼런스", - null, null, null, null, null, "코엑스", List.of("백엔드"), + null, null, null, null, null, "코엑스", List.of(백엔드), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); private static final EventResponse 모바일_컨퍼런스 = new EventResponse(null, "모바일 컨퍼런스", - null, null, null, null, null, "코엑스", List.of("백엔드"), + null, null, null, null, null, "코엑스", List.of(백엔드), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); private static final EventResponse AI_아이디어_공모전 = new EventResponse(null, "AI 아이디어 공모전", null, null, null, null, null, "코엑스", - List.of("백엔드"), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", + List.of(백엔드), "이미지1", EventType.CONFERENCE.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); private static final EventResponse 구름톤 = new EventResponse(null, "구름톤", null, - null, null, null, null, "코엑스", List.of("백엔드"), + null, null, null, null, "코엑스", List.of(백엔드), "이미지1", EventType.COMPETITION.name(), List.of(), "주최기관", PaymentType.PAID.getValue(), EventMode.ONLINE.getValue()); @@ -468,7 +470,7 @@ void findEvents_tags_filter() { final List actualEvents = eventQueryService.findEvents( EventType.CONFERENCE, TODAY, - null, null, List.of("안드로이드", "백엔드"), null, null); + null, null, List.of("안드로이드", 백엔드.getName()), null, null); // then assertThat(actualEvents) @@ -539,7 +541,8 @@ void findEvents_period_tags_filter() { final List actualEvents = eventQueryService.findEvents( EventType.CONFERENCE, TODAY, - "2023-09-01", "2023-09-30", List.of("안드로이드", "백엔드"), List.of(EventStatus.UPCOMING), null); + "2023-09-01", "2023-09-30", List.of("안드로이드", 백엔드.getName()) + , List.of(EventStatus.UPCOMING), null); // then assertThat(actualEvents) diff --git a/backend/emm-sale/src/test/java/com/emmsale/scrap/application/ScrapQueryServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/scrap/application/ScrapQueryServiceTest.java index 0112c4709..752fe42e3 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/scrap/application/ScrapQueryServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/scrap/application/ScrapQueryServiceTest.java @@ -17,7 +17,7 @@ import com.emmsale.member.domain.MemberRepository; import com.emmsale.scrap.domain.Scrap; import com.emmsale.scrap.domain.ScrapRepository; -import com.emmsale.tag.domain.Tag; +import com.emmsale.tag.application.dto.TagResponse; import java.util.List; import java.util.stream.Collectors; import org.junit.jupiter.api.DisplayName; @@ -63,7 +63,7 @@ void findAllScrapsTest() { event1.getTags() .stream() .map(EventTag::getTag) - .map(Tag::getName) + .map(TagResponse::from) .collect(Collectors.toList()), 행사_이미지1(event1.getId()).getName(), event1.getType().name(), List.of(행사_이미지2(event1.getId()).getName(), 행사_이미지3(event1.getId()).getName(), @@ -77,7 +77,7 @@ void findAllScrapsTest() { event2.getTags() .stream() .map(EventTag::getTag) - .map(Tag::getName) + .map(TagResponse::from) .collect(Collectors.toList()), null, event2.getType().name(), List.of(), From f29807349de959312bd3366c8aafcd3fd569e08b Mon Sep 17 00:00:00 2001 From: hong-sile Date: Sat, 13 Jan 2024 02:58:07 +0900 Subject: [PATCH 16/20] =?UTF-8?q?test:=20EventCommandServiceTest=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #893 --- .../application/EventCommandServiceTest.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java index 4d548ae6f..fee2afedd 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/admin/event/application/EventCommandServiceTest.java @@ -160,6 +160,13 @@ void addEventTest() { final Event savedEvent = eventRepository.findById(response.getId()).get(); //then + assertThat(response.getTags()) + .extracting("name") + .containsExactlyInAnyOrderElementsOf( + tagRequests.stream() + .map(TagRequest::getName) + .collect(Collectors.toList()) + ); assertAll( () -> assertEquals(eventName, savedEvent.getName()), () -> assertEquals(eventLocation, savedEvent.getLocation()), @@ -167,13 +174,6 @@ void addEventTest() { () -> assertEquals(beforeDateTime, savedEvent.getEventPeriod().getStartDate()), () -> assertEquals(afterDateTime, savedEvent.getEventPeriod().getEndDate()) ); - assertThat(response.getTags()) - .extracting("name") - .containsExactlyInAnyOrder( - tagRequests.stream() - .map(TagRequest::getName) - .collect(Collectors.toList()) - ); } @Test @@ -320,6 +320,13 @@ void updateEventTest() { final Event updatedEvent = eventRepository.findById(eventId).get(); //then + assertThat(response.getTags()) + .extracting("name") + .containsExactlyInAnyOrderElementsOf( + newTagRequests.stream() + .map(TagRequest::getName) + .collect(Collectors.toList()) + ); assertAll( () -> assertEquals(newName, updatedEvent.getName()), () -> assertEquals(newLocation, updatedEvent.getLocation()), @@ -327,13 +334,6 @@ void updateEventTest() { () -> assertEquals(newEndDateTime, updatedEvent.getEventPeriod().getEndDate()), () -> assertEquals(newInformationUrl, updatedEvent.getInformationUrl()) ); - assertThat(response.getTags()) - .extracting("name") - .containsExactlyInAnyOrder( - newTagRequests.stream() - .map(TagRequest::getName) - .collect(Collectors.toList()) - ); } @Test From 56b07c1f21f4f4e46d3e55d9053b724679600530 Mon Sep 17 00:00:00 2001 From: hong-sile Date: Tue, 6 Feb 2024 22:32:00 +0900 Subject: [PATCH 17/20] =?UTF-8?q?test:=20=ED=95=A8=EA=BB=98=ED=95=B4?= =?UTF-8?q?=EC=9A=94=20=EC=9A=94=EC=B2=AD=20=EB=B0=98=ED=99=98=EA=B0=92=20?= =?UTF-8?q?API=20Test=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #908 --- .../documentTest/java/com/emmsale/RecruitmentPostApiTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java index 17c61de19..60ff117bf 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java @@ -47,7 +47,8 @@ class RecruitmentPostApiTest extends MockMvcTestHelper { .description("member의 이미지 url"), fieldWithPath("[].member.githubUrl").type(JsonFieldType.STRING) .description("member의 github Url"), - fieldWithPath("[].eventId").type(JsonFieldType.NUMBER).description("행사의 식별자") + fieldWithPath("[].eventId").type(JsonFieldType.NUMBER).description("행사의 식별자"), + fieldWithPath("[].eventName").type(JsonFieldType.STRING).description("행사의 이름") ); private static final ResponseFieldsSnippet RECRUITMENT_POST_RESPONSE_FIELDS = responseFields( From 289740c3cf7c5f7d2e7cd4fcc70d81eda3097e4c Mon Sep 17 00:00:00 2001 From: hong-sile Date: Tue, 6 Feb 2024 22:45:52 +0900 Subject: [PATCH 18/20] =?UTF-8?q?feat:=20RecruitmentPostQueryResponse=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=EA=B0=92=EC=97=90=20eventName=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #908 --- .../java/com/emmsale/RecruitmentPostApiTest.java | 13 ++++++------- .../com/emmsale/event/api/RecruitmentPostApi.java | 9 ++++----- .../dto/RecruitmentPostQueryResponse.java | 4 +++- .../RecruitmentPostQueryServiceTest.java | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java index 60ff117bf..350f131d5 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java @@ -126,9 +126,9 @@ void findRecruitmentPosts() throws Exception { final LocalDate postedAt = LocalDate.of(2023, 7, 15); final List response = List.of( new RecruitmentPostQueryResponse(1L, "함께해요~", postedAt, - MemberReferenceResponse.from(member1), 21L), + MemberReferenceResponse.from(member1), 21L, "21번 행사"), new RecruitmentPostQueryResponse(2L, "같이 가요~", postedAt, - MemberReferenceResponse.from(member2), 43L) + MemberReferenceResponse.from(member2), 43L, "43번 행사") ); when(postQueryService.findRecruitmentPosts(eventId)).thenReturn(response); @@ -151,7 +151,7 @@ void findRecruitmentPost() throws Exception { final RecruitmentPostQueryResponse response = new RecruitmentPostQueryResponse(1L, "함께해요~", postedAt, - MemberReferenceResponse.from(member), 21L); + MemberReferenceResponse.from(member), 21L, "21번 행사"); when(postQueryService.findRecruitmentPost(eventId, postId)).thenReturn(response); //when && then @@ -213,9 +213,9 @@ void findRecruitmentPostsByMemberIdTest() throws Exception { final LocalDate postedAt = LocalDate.of(2023, 7, 15); final List response = List.of( new RecruitmentPostQueryResponse(1L, "함께해요~", postedAt, - MemberReferenceResponse.from(member), 21L), + MemberReferenceResponse.from(member), 21L,"21번 행사"), new RecruitmentPostQueryResponse(2L, "같이 가요~", postedAt, - MemberReferenceResponse.from(member), 43L) + MemberReferenceResponse.from(member), 43L, "43번 행사") ); //when @@ -223,8 +223,7 @@ void findRecruitmentPostsByMemberIdTest() throws Exception { //then mockMvc.perform( - get("/events/recruitment-posts?member-id={memberId}", - memberId) + get("/events/recruitment-posts?member-id={memberId}", memberId) .header(HttpHeaders.AUTHORIZATION, "Bearer AccessToken")) .andExpect(status().isOk()) .andDo(document("find-all-by-member-id-recruitment-post", diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/api/RecruitmentPostApi.java b/backend/emm-sale/src/main/java/com/emmsale/event/api/RecruitmentPostApi.java index 96d4f7b83..7dcc592e6 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/api/RecruitmentPostApi.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/api/RecruitmentPostApi.java @@ -12,7 +12,6 @@ import java.util.List; import javax.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -22,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @RestController @@ -95,11 +93,12 @@ public ResponseEntity isAlreadyRecruit( } @GetMapping("/recruitment-posts") - @ResponseStatus(HttpStatus.OK) - public List findRecruitmentPostsByMemberId( + public ResponseEntity> findRecruitmentPostsByMemberId( final Member member, @RequestParam("member-id") final Long memberId ) { - return postQueryService.findRecruitmentPostsByMemberId(member, memberId); + final List responses + = postQueryService.findRecruitmentPostsByMemberId(member, memberId); + return ResponseEntity.ok(responses); } } diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/RecruitmentPostQueryResponse.java b/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/RecruitmentPostQueryResponse.java index 0740f7826..cd6e0e592 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/RecruitmentPostQueryResponse.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/application/dto/RecruitmentPostQueryResponse.java @@ -20,6 +20,7 @@ public class RecruitmentPostQueryResponse { private final LocalDate updatedAt; private final MemberReferenceResponse member; private final Long eventId; + private final String eventName; public static RecruitmentPostQueryResponse from(final RecruitmentPost recruitmentPost) { final Member member = recruitmentPost.getMember(); @@ -28,7 +29,8 @@ public static RecruitmentPostQueryResponse from(final RecruitmentPost recruitmen recruitmentPost.getContent(), recruitmentPost.getUpdatedAt().toLocalDate(), MemberReferenceResponse.from(member), - recruitmentPost.getEvent().getId() + recruitmentPost.getEvent().getId(), + recruitmentPost.getEvent().getName() ); } } diff --git a/backend/emm-sale/src/test/java/com/emmsale/event/application/RecruitmentPostQueryServiceTest.java b/backend/emm-sale/src/test/java/com/emmsale/event/application/RecruitmentPostQueryServiceTest.java index 82cd71375..300c42d10 100644 --- a/backend/emm-sale/src/test/java/com/emmsale/event/application/RecruitmentPostQueryServiceTest.java +++ b/backend/emm-sale/src/test/java/com/emmsale/event/application/RecruitmentPostQueryServiceTest.java @@ -67,9 +67,9 @@ void findRecruitmentPosts() { final List expected = List.of( new RecruitmentPostQueryResponse(멤버1_참가글_ID, requestMember1.getContent(), LocalDate.now(), - MemberReferenceResponse.from(사용자1), 인프콘.getId()), + MemberReferenceResponse.from(사용자1), 인프콘.getId(), 인프콘.getName()), new RecruitmentPostQueryResponse(멤버2_참가글_ID, requestMember2.getContent(), LocalDate.now(), - MemberReferenceResponse.from(사용자2), 인프콘.getId()) + MemberReferenceResponse.from(사용자2), 인프콘.getId(), 인프콘.getName()) ); //when @@ -93,7 +93,7 @@ void findRecruitmentPost() { final RecruitmentPostQueryResponse expected = new RecruitmentPostQueryResponse(멤버1_참가글_ID, requestMember1.getContent(), LocalDate.now(), MemberReferenceResponse.from(사용자1), - 인프콘.getId()); + 인프콘.getId(), 인프콘.getName()); //when final RecruitmentPostQueryResponse actual = postQueryService.findRecruitmentPost( From 92d260ba5043a81b9f55b5c27ce0ae87815ed543 Mon Sep 17 00:00:00 2001 From: hong-sile Date: Tue, 6 Feb 2024 22:46:18 +0900 Subject: [PATCH 19/20] =?UTF-8?q?refactor:=20findAllByMember=EC=97=90?= =?UTF-8?q?=EC=84=9C=20event=EC=9D=B4=EB=A6=84=EB=8F=84=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=EC=98=A4=EB=AF=80=EB=A1=9C=20event=20fetch=20join?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #908 --- .../event/domain/repository/RecruitmentPostRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/RecruitmentPostRepository.java b/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/RecruitmentPostRepository.java index 260aa41da..9bf80b910 100644 --- a/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/RecruitmentPostRepository.java +++ b/backend/emm-sale/src/main/java/com/emmsale/event/domain/repository/RecruitmentPostRepository.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository @@ -14,5 +15,8 @@ public interface RecruitmentPostRepository extends JpaRepository findAllByMember(Member member); } From 7b2a61b13da6178bce3f07c953fe3cc95445e672 Mon Sep 17 00:00:00 2001 From: hong-sile Date: Tue, 6 Feb 2024 22:52:00 +0900 Subject: [PATCH 20/20] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 #908 --- .../documentTest/java/com/emmsale/RecruitmentPostApiTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java b/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java index 350f131d5..cc8ad1ad6 100644 --- a/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java +++ b/backend/emm-sale/src/documentTest/java/com/emmsale/RecruitmentPostApiTest.java @@ -63,7 +63,8 @@ class RecruitmentPostApiTest extends MockMvcTestHelper { .description("member의 이미지 url"), fieldWithPath("member.githubUrl").type(JsonFieldType.STRING) .description("member의 github Url"), - fieldWithPath("eventId").type(JsonFieldType.NUMBER).description("행사의 식별자") + fieldWithPath("eventId").type(JsonFieldType.NUMBER).description("행사의 식별자"), + fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사의 이름") ); @Test