From 1626cb9ff1c4b18e80c683d7da2df424cf8e8cc1 Mon Sep 17 00:00:00 2001 From: Jinwoo Lee Date: Thu, 12 Oct 2023 14:30:40 +0900 Subject: [PATCH 1/5] feat: implement delete device-token logic --- .../auth/service/DeviceTokenService.java | 11 +++++++++ .../controller/NotificationController.java | 23 +++++++++++++++++++ .../service/NotificationService.java | 9 ++++++++ 3 files changed, 43 insertions(+) diff --git a/src/main/java/org/swmaestro/repl/gifthub/auth/service/DeviceTokenService.java b/src/main/java/org/swmaestro/repl/gifthub/auth/service/DeviceTokenService.java index 8155e3bb..67129e93 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/auth/service/DeviceTokenService.java +++ b/src/main/java/org/swmaestro/repl/gifthub/auth/service/DeviceTokenService.java @@ -96,6 +96,17 @@ public DeviceToken read(Long deviceTokenId) { .orElseThrow(() -> new BusinessException("존재하지 않는 토큰입니다.", StatusEnum.INTERNAL_SERVER_ERROR)); } + /* + * DeviceToken 삭제 메서드 + */ + public void delete(Member member, String token) { + DeviceToken deviceToken = read(token); + if (!deviceToken.getMember().equals(member)) { + throw new BusinessException("토큰을 삭제할 권한이 없습니다.", StatusEnum.FORBIDDEN); + } + deviceTokenRepository.delete(deviceToken); + } + /* * DeviceToken 삭제 메서드 (token) */ diff --git a/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java b/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java index 28fdd9e2..938465a5 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java +++ b/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java @@ -10,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.swmaestro.repl.gifthub.auth.entity.Member; +import org.swmaestro.repl.gifthub.auth.service.MemberService; import org.swmaestro.repl.gifthub.notifications.dto.DeviceTokenSaveRequestDto; import org.swmaestro.repl.gifthub.notifications.dto.NoticeNotificationDto; import org.swmaestro.repl.gifthub.notifications.dto.NotificationReadResponseDto; @@ -33,6 +35,7 @@ public class NotificationController { private final NotificationService notificationService; private final FCMNotificationService fcmNotificationService; + private final MemberService memberService; private final JwtProvider jwtProvider; @GetMapping @@ -71,6 +74,26 @@ public ResponseEntity registerDeviceToken( .build()); } + @PostMapping("/device") + @Operation(summary = "디바이스 토큰 삭제 메서드", description = "알림 서비스를 위한 디바이스 토큰을 삭제하기 위한 메서드입니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "디바이스 토큰 등록 성공"), + @ApiResponse(responseCode = "400(400)", description = "존재하지 토큰 등록 시도"), + @ApiResponse(responseCode = "400(404)", description = "존재하지 않는 회원"), + }) + public ResponseEntity deleteDeviceToken( + HttpServletRequest request, + @RequestHeader("Authorization") String accessToken, + @RequestBody DeviceTokenSaveRequestDto deviceTokenSaveRequestDto) { + String username = jwtProvider.getUsername(accessToken.substring(7)); + Member member = memberService.read(username); + notificationService.deleteDeviceToken(member, deviceTokenSaveRequestDto.getToken()); + return ResponseEntity.ok( + SuccessMessage.builder() + .path(request.getRequestURI()) + .build()); + } + @GetMapping("/{notificationId}") @Operation(summary = "Notification 상세 조회 메서드", description = "클라이언트에서 요청한 알림 상세 정보를 조회하기 위한 메서드입니다. 응답으로 알림 type, message, notified date, 기프티콘 정보, 기존 알림 확인 시간을 반환합니다.") @ApiResponses({ diff --git a/src/main/java/org/swmaestro/repl/gifthub/notifications/service/NotificationService.java b/src/main/java/org/swmaestro/repl/gifthub/notifications/service/NotificationService.java index 5a8461e7..7a82f46c 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/notifications/service/NotificationService.java +++ b/src/main/java/org/swmaestro/repl/gifthub/notifications/service/NotificationService.java @@ -69,6 +69,15 @@ public boolean saveDeviceToken(String username, String deviceToken) { } + public boolean deleteDeviceToken(Member member, String deviceToken) { + try { + deviceTokenService.delete(member, deviceToken); + return true; + } catch (Exception e) { + throw new BusinessException("디바이스 토큰 삭제에 실패하였습니다.", StatusEnum.BAD_REQUEST); + } + } + /** * Notification 저장 메서드 */ From 49d038730a6bfbdcd620a19e08606c283868bd18 Mon Sep 17 00:00:00 2001 From: Jinwoo Lee Date: Thu, 12 Oct 2023 14:49:24 +0900 Subject: [PATCH 2/5] chore: rename dto-class-name --- .../controller/NotificationController.java | 10 ++++----- ...estDto.java => DeviceTokenRequestDto.java} | 4 ++-- .../NotificationControllerTest.java | 21 ++++++++++++++----- 3 files changed, 23 insertions(+), 12 deletions(-) rename src/main/java/org/swmaestro/repl/gifthub/notifications/dto/{DeviceTokenSaveRequestDto.java => DeviceTokenRequestDto.java} (83%) diff --git a/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java b/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java index 938465a5..b4ecf780 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java +++ b/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController; import org.swmaestro.repl.gifthub.auth.entity.Member; import org.swmaestro.repl.gifthub.auth.service.MemberService; -import org.swmaestro.repl.gifthub.notifications.dto.DeviceTokenSaveRequestDto; +import org.swmaestro.repl.gifthub.notifications.dto.DeviceTokenRequestDto; import org.swmaestro.repl.gifthub.notifications.dto.NoticeNotificationDto; import org.swmaestro.repl.gifthub.notifications.dto.NotificationReadResponseDto; import org.swmaestro.repl.gifthub.notifications.service.FCMNotificationService; @@ -65,9 +65,9 @@ public ResponseEntity listNotification(HttpServletRequest request) { public ResponseEntity registerDeviceToken( HttpServletRequest request, @RequestHeader("Authorization") String accessToken, - @RequestBody DeviceTokenSaveRequestDto deviceTokenSaveRequestDto) { + @RequestBody DeviceTokenRequestDto deviceTokenRequestDto) { String username = jwtProvider.getUsername(accessToken.substring(7)); - notificationService.saveDeviceToken(username, deviceTokenSaveRequestDto.getToken()); + notificationService.saveDeviceToken(username, deviceTokenRequestDto.getToken()); return ResponseEntity.ok( SuccessMessage.builder() .path(request.getRequestURI()) @@ -84,10 +84,10 @@ public ResponseEntity registerDeviceToken( public ResponseEntity deleteDeviceToken( HttpServletRequest request, @RequestHeader("Authorization") String accessToken, - @RequestBody DeviceTokenSaveRequestDto deviceTokenSaveRequestDto) { + @RequestBody DeviceTokenRequestDto deviceTokenRequestDto) { String username = jwtProvider.getUsername(accessToken.substring(7)); Member member = memberService.read(username); - notificationService.deleteDeviceToken(member, deviceTokenSaveRequestDto.getToken()); + notificationService.deleteDeviceToken(member, deviceTokenRequestDto.getToken()); return ResponseEntity.ok( SuccessMessage.builder() .path(request.getRequestURI()) diff --git a/src/main/java/org/swmaestro/repl/gifthub/notifications/dto/DeviceTokenSaveRequestDto.java b/src/main/java/org/swmaestro/repl/gifthub/notifications/dto/DeviceTokenRequestDto.java similarity index 83% rename from src/main/java/org/swmaestro/repl/gifthub/notifications/dto/DeviceTokenSaveRequestDto.java rename to src/main/java/org/swmaestro/repl/gifthub/notifications/dto/DeviceTokenRequestDto.java index ba3529de..b991b9b5 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/notifications/dto/DeviceTokenSaveRequestDto.java +++ b/src/main/java/org/swmaestro/repl/gifthub/notifications/dto/DeviceTokenRequestDto.java @@ -11,11 +11,11 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) -public class DeviceTokenSaveRequestDto { +public class DeviceTokenRequestDto { private String token; @Builder - public DeviceTokenSaveRequestDto(String token) { + public DeviceTokenRequestDto(String token) { this.token = token; } } diff --git a/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java b/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java index a5bbba47..a6ad9443 100644 --- a/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java +++ b/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java @@ -16,7 +16,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; -import org.swmaestro.repl.gifthub.notifications.dto.DeviceTokenSaveRequestDto; +import org.swmaestro.repl.gifthub.notifications.dto.DeviceTokenRequestDto; import org.swmaestro.repl.gifthub.notifications.dto.NotificationReadResponseDto; import org.swmaestro.repl.gifthub.notifications.service.NotificationService; import org.swmaestro.repl.gifthub.util.JwtProvider; @@ -78,17 +78,17 @@ void saveDeviceToken() throws Exception { // given String accessToken = "my.access.token"; String username = "이진우"; - DeviceTokenSaveRequestDto deviceTokenSaveRequestDto = DeviceTokenSaveRequestDto.builder().token("my.device.token").build(); + DeviceTokenRequestDto deviceTokenRequestDto = DeviceTokenRequestDto.builder().token("my.device.token").build(); // when when(jwtProvider.resolveToken(any())).thenReturn(accessToken); when(jwtProvider.getUsername(anyString())).thenReturn(username); - when(notificationService.saveDeviceToken(username, deviceTokenSaveRequestDto.getToken())).thenReturn(true); + when(notificationService.saveDeviceToken(username, deviceTokenRequestDto.getToken())).thenReturn(true); // then mockMvc.perform(post("/notifications/device").header("Authorization", "Bearer " + accessToken) - .contentType("application/json") - .content(objectMapper.writeValueAsString(deviceTokenSaveRequestDto))) + .contentType("agipplication/json") + .content(objectMapper.writeValueAsString(deviceTokenRequestDto))) .andExpect(status().isOk()) .andReturn(); } @@ -118,4 +118,15 @@ void readNotificationTest() throws Exception { .andExpect(status().isOk()) .andReturn(); } + + @Test + @WithMockUser(username = "이진우", roles = "USER") + void deleteDeviceToken() { + String accessToken = "my.access.token"; + String username = "이진우"; + + when(jwtProvider.resolveToken(any())).thenReturn(accessToken); + when(jwtProvider.getUsername(anyString())).thenReturn(username); + when(notificationService.saveDeviceToken(username, deviceTokenSaveRequestDto.getToken())).thenReturn(true); + } } From b8b40115173bde5f18e09448d42ba1a9772d7d47 Mon Sep 17 00:00:00 2001 From: Jinwoo Lee Date: Thu, 12 Oct 2023 15:04:10 +0900 Subject: [PATCH 3/5] feat: implement delete device-token api --- .../notifications/controller/NotificationController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java b/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java index b4ecf780..39b94f74 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java +++ b/src/main/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationController.java @@ -3,6 +3,7 @@ import java.util.List; 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; @@ -74,7 +75,7 @@ public ResponseEntity registerDeviceToken( .build()); } - @PostMapping("/device") + @DeleteMapping("/device") @Operation(summary = "디바이스 토큰 삭제 메서드", description = "알림 서비스를 위한 디바이스 토큰을 삭제하기 위한 메서드입니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "디바이스 토큰 등록 성공"), From f8a9fe07b16164867251279226a0b50b2702724f Mon Sep 17 00:00:00 2001 From: Jinwoo Lee Date: Thu, 12 Oct 2023 15:04:26 +0900 Subject: [PATCH 4/5] test: write delete device-token-api test --- .../controller/NotificationControllerTest.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java b/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java index a6ad9443..a8947442 100644 --- a/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java +++ b/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java @@ -16,6 +16,8 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; +import org.swmaestro.repl.gifthub.auth.entity.Member; +import org.swmaestro.repl.gifthub.auth.service.MemberService; import org.swmaestro.repl.gifthub.notifications.dto.DeviceTokenRequestDto; import org.swmaestro.repl.gifthub.notifications.dto.NotificationReadResponseDto; import org.swmaestro.repl.gifthub.notifications.service.NotificationService; @@ -38,6 +40,9 @@ public class NotificationControllerTest { @MockBean private NotificationService notificationService; + @MockBean + private MemberService memberService; + /** * 알림 목록 조회 테스트 */ @@ -121,12 +126,20 @@ void readNotificationTest() throws Exception { @Test @WithMockUser(username = "이진우", roles = "USER") - void deleteDeviceToken() { + void deleteDeviceToken() throws Exception { String accessToken = "my.access.token"; String username = "이진우"; + DeviceTokenRequestDto deviceTokenRequestDto = DeviceTokenRequestDto.builder().token("my.device.token").build(); + Member member = Member.builder().username(username).build(); when(jwtProvider.resolveToken(any())).thenReturn(accessToken); when(jwtProvider.getUsername(anyString())).thenReturn(username); - when(notificationService.saveDeviceToken(username, deviceTokenSaveRequestDto.getToken())).thenReturn(true); + when(memberService.read(username)).thenReturn(member); + when(notificationService.deleteDeviceToken(member, deviceTokenRequestDto.getToken())).thenReturn(true); + + mockMvc.perform(delete("/notifications/device").header("Authorization", "Bearer " + accessToken) + .contentType("application/json") + .content(objectMapper.writeValueAsString(deviceTokenRequestDto))) + .andExpect(status().isOk()); } } From c3e6c9e9f73554740e88cf52b227e8d7f6d80d08 Mon Sep 17 00:00:00 2001 From: Jinwoo Lee Date: Thu, 12 Oct 2023 15:11:34 +0900 Subject: [PATCH 5/5] chore: remove typo --- .../notifications/controller/NotificationControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java b/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java index a8947442..19076f2c 100644 --- a/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java +++ b/src/test/java/org/swmaestro/repl/gifthub/notifications/controller/NotificationControllerTest.java @@ -92,7 +92,7 @@ void saveDeviceToken() throws Exception { // then mockMvc.perform(post("/notifications/device").header("Authorization", "Bearer " + accessToken) - .contentType("agipplication/json") + .contentType("application/json") .content(objectMapper.writeValueAsString(deviceTokenRequestDto))) .andExpect(status().isOk()) .andReturn();