From ca08713db3b8be9552def840c961f1ef8bf3b1e2 Mon Sep 17 00:00:00 2001 From: j-yong99 Date: Tue, 14 May 2024 19:47:09 +0900 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moment/auth/client/CoreClient.java | 9 +- .../auth/controller/AuthController.java | 24 ++ .../com/moment/auth/service/AuthService.java | 2 + .../com/moment/auth/service/UserService.java | 16 ++ .../auth/controller/AuthControllerTest.java | 29 +++ .../core/controller/UserController.java | 16 ++ .../AlreadyBookedDateRepository.java | 2 + .../domain/cardView/CardViewRepository.java | 3 + .../domain/imageFile/ImageFileRepository.java | 5 + .../domain/receipt/ReceiptRepository.java | 3 + .../core/domain/trip/TripRepository.java | 3 +- .../domain/tripFile/TripFileRepository.java | 2 + .../com/moment/core/service/UserService.java | 29 +++ .../moment/gateway/filter/GlobalFilter.java | 5 +- .../src/main/resources/static/docs/index.html | 238 ++++++++++++++---- .../notification/DTO/FcmMessageDto.java | 9 + .../notification/service/FcmService.java | 4 +- 17 files changed, 348 insertions(+), 51 deletions(-) diff --git a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/client/CoreClient.java b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/client/CoreClient.java index 193d50f886..9f9c9a27d0 100644 --- a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/client/CoreClient.java +++ b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/client/CoreClient.java @@ -5,12 +5,17 @@ import com.moment.auth.dto.request.UserRequestDTO; import org.springframework.cloud.openfeign.FeignClient; 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.*; @FeignClient(name = "core-service") public interface CoreClient { @PostMapping("/core/user/register") ResponseEntity registerUser(UserRequestDTO.registerUser request); + + @DeleteMapping("/core/user/{userId}") + ResponseEntity deleteUser(@PathVariable Long userId); + + @GetMapping("/core/user/test") + ResponseEntity test(); } diff --git a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/controller/AuthController.java b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/controller/AuthController.java index b599c3012d..49a9f1ef2b 100644 --- a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/controller/AuthController.java +++ b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/controller/AuthController.java @@ -1,16 +1,20 @@ package com.moment.auth.controller; +import com.moment.auth.client.CoreClient; import com.moment.auth.common.APIResponse; import com.moment.auth.common.code.SuccessCode; import com.moment.auth.dto.request.AuthRequest; import com.moment.auth.dto.response.TokenResponseDTO; import com.moment.auth.service.AuthService; +import com.moment.auth.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.ErrorResponse; import org.springframework.web.bind.annotation.*; @@ -18,8 +22,11 @@ @RestController @RequiredArgsConstructor @RequestMapping("/auth") +@Slf4j public class AuthController { private final AuthService authService; + private final UserService userService; + private final CoreClient coreClient; // 로그인 @PostMapping("/login") public ResponseEntity> login( @@ -66,4 +73,21 @@ public ResponseEntity changePassword( authService.changePassword(changePassword, userId); return ResponseEntity.ok(APIResponse.of(SuccessCode.UPDATE_SUCCESS)); } + + // 회원 탈퇴 + @DeleteMapping("/delete") + public ResponseEntity deleteAccount( + @RequestHeader Long userId + ) { + userService.deleteAccount(userId); + return ResponseEntity.ok(APIResponse.of(SuccessCode.DELETE_SUCCESS)); + } + + // 테스트 + @GetMapping("/test") + public ResponseEntity test() { + log.info("test"); + coreClient.test(); + return new ResponseEntity<>("test", HttpStatus.OK); + } } diff --git a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/AuthService.java b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/AuthService.java index 326193bd4f..f426d12bcf 100644 --- a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/AuthService.java +++ b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/AuthService.java @@ -1,5 +1,6 @@ package com.moment.auth.service; +import com.moment.auth.client.CoreClient; import com.moment.auth.domain.Role; import com.moment.auth.domain.user.User; import com.moment.auth.domain.user.UserRepository; @@ -120,4 +121,5 @@ public void changePassword(AuthRequest.ChangePassword changePassword, Long userI user.setPassword(passwordEncoder.encode(changePassword.getNewPassword())); userService.save(user); } + } diff --git a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/UserService.java b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/UserService.java index 8bdd11354d..d2432ee1d8 100644 --- a/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/UserService.java +++ b/backend/moment/moment-server/auth/src/main/java/com/moment/auth/service/UserService.java @@ -4,8 +4,10 @@ import com.moment.auth.domain.user.User; import com.moment.auth.domain.user.UserRepository; import com.moment.auth.dto.request.UserRequestDTO; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatusCode; import org.springframework.stereotype.Service; @Service @@ -36,4 +38,18 @@ public void registerUserToCoreServer(User user) { } } + @Transactional + public void deleteAccount(Long userId) { + try{ + log.info("Core 서버에 유저 삭제를 시도합니다."); + HttpStatusCode statusCode = coreClient.deleteUser(userId).getStatusCode(); + if(!statusCode.is2xxSuccessful()){ + throw new RuntimeException("Core 서버에 유저 삭제에 실패했습니다."); + } + userRepository.deleteById(userId); + + }catch (Exception e){ + throw new RuntimeException("Core 서버에 유저 삭제에 실패했습니다."); + } + } } diff --git a/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java index d712bc3ef4..5f19c7054b 100644 --- a/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java +++ b/backend/moment/moment-server/auth/src/test/java/com/moment/auth/controller/AuthControllerTest.java @@ -4,6 +4,7 @@ import com.moment.auth.dto.request.AuthRequest; import com.moment.auth.dto.response.TokenResponseDTO; import com.moment.auth.service.AuthService; +import com.moment.auth.service.UserService; import io.swagger.v3.core.util.Json; import jakarta.ws.rs.core.MediaType; import org.junit.jupiter.api.Test; @@ -40,6 +41,9 @@ class AuthControllerTest { @MockBean private AuthService authService; + @MockBean + private UserService userService; + @InjectMocks private AuthController authController; @@ -202,4 +206,29 @@ void changePassword() throws Exception { )) .andDo(print()); } + + @Test + void deleteAccount() throws Exception { + + Mockito.doNothing().when(userService).deleteAccount(any()); + + mockMvc.perform(RestDocumentationRequestBuilders.delete("/auth/delete") + .header("userId", 1L)) + .andExpect(status().isOk()) + .andDo(document("auth/deleteAccount", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()), + requestHeaders( + headerWithName("userId").description("Bearer Token") + ), + responseFields( + fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"), + fieldWithPath("code").type(JsonFieldType.STRING).description("응답 코드"), + fieldWithPath("msg").type(JsonFieldType.STRING).description("응답 메시지"), + fieldWithPath("detailMsg").type(JsonFieldType.STRING).description("상세 메시지"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("데이터 없음") + ) + )) + .andDo(print()); + } } \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/UserController.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/UserController.java index c490ca2d9d..f483db8423 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/UserController.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/UserController.java @@ -63,4 +63,20 @@ public ResponseEntity updateUserSetting( userService.updateUserSetting(request, userId); return ResponseEntity.ok(APIResponse.of(SuccessCode.UPDATE_SUCCESS)); } + + // 유저 탈퇴 + @DeleteMapping("/{userId}") + public ResponseEntity deleteUser( + @PathVariable Long userId + ) { + log.info("delete userId : {}", userId); + userService.deleteUser(userId); + return ResponseEntity.ok(APIResponse.of(SuccessCode.DELETE_SUCCESS)); + } + // 테스트 + @GetMapping("/test") + public ResponseEntity test() { + log.info("test"); + return new ResponseEntity<>("test", HttpStatus.OK); + } } diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/alreadyBookedDate/AlreadyBookedDateRepository.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/alreadyBookedDate/AlreadyBookedDateRepository.java index 27d8411ff6..2e74a3b3ff 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/alreadyBookedDate/AlreadyBookedDateRepository.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/alreadyBookedDate/AlreadyBookedDateRepository.java @@ -14,4 +14,6 @@ public interface AlreadyBookedDateRepository extends JpaRepository findAllByUserOrderByYearDate(User user); + + void deleteAllByUser(User user); } \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/cardView/CardViewRepository.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/cardView/CardViewRepository.java index 194dba0e00..e4ffe002b8 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/cardView/CardViewRepository.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/cardView/CardViewRepository.java @@ -1,6 +1,7 @@ package com.moment.core.domain.cardView; import com.moment.core.domain.tripFile.TripFile; +import com.moment.core.domain.user.User; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; @@ -23,4 +24,6 @@ public interface CardViewRepository extends JpaRepository { @Override @EntityGraph(attributePaths = {"tripFile"}) Optional findById(Long id); + + void deleteAllByTripFile_User(User user); } \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/imageFile/ImageFileRepository.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/imageFile/ImageFileRepository.java index 57bc65cd86..6e262e7a17 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/imageFile/ImageFileRepository.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/imageFile/ImageFileRepository.java @@ -1,6 +1,7 @@ package com.moment.core.domain.imageFile; import com.moment.core.domain.cardView.CardView; +import com.moment.core.domain.user.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; @@ -9,4 +10,8 @@ public interface ImageFileRepository extends JpaRepository { List findAllByCardView_Id(Long cardViewId); List findAllByCardView(CardView cardView); + + + + void deleteAllByCardView_TripFile_User(User user); } \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/receipt/ReceiptRepository.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/receipt/ReceiptRepository.java index e4dbc60e56..3c365280dd 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/receipt/ReceiptRepository.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/receipt/ReceiptRepository.java @@ -1,6 +1,7 @@ package com.moment.core.domain.receipt; import com.moment.core.domain.trip.Trip; +import com.moment.core.domain.user.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -26,4 +27,6 @@ public interface ReceiptRepository extends PagingAndSortingRepository findAllByTrip(Trip trip); + + void deleteAllByUser(User user); } diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/trip/TripRepository.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/trip/TripRepository.java index 4c4ddcd636..3b7a8b25b4 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/trip/TripRepository.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/trip/TripRepository.java @@ -2,7 +2,6 @@ import com.moment.core.domain.user.User; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Optional; @@ -14,5 +13,5 @@ public interface TripRepository extends JpaRepository { List findAllByUserAndIsNotTitledOrderByStartDate(User user, boolean b); - + void deleteAllByUser(User user); } \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/tripFile/TripFileRepository.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/tripFile/TripFileRepository.java index cf4c8f73ca..b95a33ba65 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/tripFile/TripFileRepository.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/domain/tripFile/TripFileRepository.java @@ -20,4 +20,6 @@ public interface TripFileRepository extends JpaRepository { List findByTrip(Trip trip); List findAllByTrip(Trip trip); + + void deleteAllByUser(User user); } \ No newline at end of file diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/service/UserService.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/service/UserService.java index 2ad5a79c99..00208d0a6b 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/service/UserService.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/service/UserService.java @@ -1,7 +1,10 @@ package com.moment.core.service; +import com.moment.core.domain.alreadyBookedDate.AlreadyBookedDateRepository; import com.moment.core.domain.cardView.CardView; import com.moment.core.domain.cardView.CardViewRepository; +import com.moment.core.domain.imageFile.ImageFileRepository; +import com.moment.core.domain.receipt.ReceiptRepository; import com.moment.core.domain.trip.Trip; import com.moment.core.domain.trip.TripRepository; import com.moment.core.domain.tripFile.TripFile; @@ -29,6 +32,11 @@ public class UserService { private final EntityManager em; private final TripFileRepository tripFileRepository; private final CardViewRepository cardViewRepository; + private final S3Service s3Service; + private final ReceiptRepository receiptRepository; + private final ImageFileRepository imageFileRepository; + private final AlreadyBookedDateRepository alreadyBookedDateRepository; + @Transactional public User save(UserRequestDTO.registerUser request) { @@ -82,4 +90,25 @@ public void updateUserSetting(UserRequestDTO.updateUser request, Long userId) { user.setFirebaseToken(request.getFirebaseToken()); userRepository.save(user); } + + @Transactional + public void deleteUser(Long userId) { + User user = userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다.")); + // S3 먼저 전부 삭제 +// s3Service.deleteFile("", String.valueOf(userId)); + // 유저의 영수증 전부 삭제 + receiptRepository.deleteAllByUser(user); + // 유저의 imageFile 전부 삭제 + imageFileRepository.deleteAllByCardView_TripFile_User(user); + // 카드뷰 전부 삭제 + cardViewRepository.deleteAllByTripFile_User(user); + // 여행파일 전부 삭제 + tripFileRepository.deleteAllByUser(user); + // 여행 삭제 + tripRepository.deleteAllByUser(user); + // alreadyBookedDate 삭제 + alreadyBookedDateRepository.deleteAllByUser(user); + // 유저 삭제 + userRepository.delete(user); + } } diff --git a/backend/moment/moment-server/gateway/src/main/java/com/moment/gateway/filter/GlobalFilter.java b/backend/moment/moment-server/gateway/src/main/java/com/moment/gateway/filter/GlobalFilter.java index 96edb924ea..048d8c43c3 100644 --- a/backend/moment/moment-server/gateway/src/main/java/com/moment/gateway/filter/GlobalFilter.java +++ b/backend/moment/moment-server/gateway/src/main/java/com/moment/gateway/filter/GlobalFilter.java @@ -20,7 +20,10 @@ public GatewayFilter apply(Config config){ ServerHttpResponse response = exchange.getResponse(); // log.info("global filter baseMessage: {}",config.getBaseMessage()); if (config.isPreLogger()){ - log.info("Global Filter Start: request id->{}",request.getId()); + log.info("Global Filter Start: request id->{}",request.getLocalAddress()); + log.info("Global Filter Start: request path->{}",request.getURI()); + log.info("Global Filter Start: request Body->{}",request.getBody()); + } return chain.filter(exchange).then(Mono.fromRunnable(() ->{ if(config.isPreLogger()){ diff --git a/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html b/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html index 8787a04128..723dc9b75d 100644 --- a/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html +++ b/backend/moment/moment-server/gateway/src/main/resources/static/docs/index.html @@ -571,6 +571,18 @@

Moment Application API Document

  • Response fields
  • +
  • 회원탈퇴 + +
  • Trip @@ -811,7 +823,7 @@

    +

    회원탈퇴

    +
    +

    Curl request

    +
    +
    +
    $ curl 'http://localhost:8080/auth/delete' -i -X DELETE \
    +    -H 'userId: 1'
    +
    +
    +
    +
    +

    HTTP request

    +
    +
    +
    DELETE /auth/delete HTTP/1.1
    +userId: 1
    +Host: localhost:8080
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json
    +Content-Length: 102
    +
    +{
    +  "status" : 200,
    +  "code" : "200",
    +  "msg" : "DELETE SUCCESS",
    +  "detailMsg" : "",
    +  "data" : { }
    +}
    +
    +
    +
    +
    +

    HTTPie request

    +
    +
    +
    $ http DELETE 'http://localhost:8080/auth/delete' \
    +    'userId:1'
    +
    +
    +
    +
    +

    Request body

    +
    +
    +
    +
    +
    +
    +
    +

    Request headers

    + ++++ + + + + + + + + + + + + +
    NameDescription

    userId

    Bearer Token

    +
    +
    +

    Response body

    +
    +
    +
    {
    +  "status" : 200,
    +  "code" : "200",
    +  "msg" : "DELETE SUCCESS",
    +  "detailMsg" : "",
    +  "data" : { }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    status

    Number

    응답 상태 코드

    code

    String

    응답 코드

    msg

    String

    응답 메시지

    detailMsg

    String

    상세 메시지

    data

    Object

    데이터 없음

    +
    +
    @@ -2865,8 +3013,8 @@

    @@ -2884,8 +3032,8 @@

    @@ -2914,8 +3062,8 @@

    @@ -3316,8 +3464,8 @@

    @@ -3347,8 +3495,8 @@

    $ echo '{
       "tripId" : 1,
    -  "startDate" : "2024-05-09",
    -  "endDate" : "2024-05-10",
    +  "startDate" : "2024-05-14",
    +  "endDate" : "2024-05-15",
       "tripName" : "test"
     }' | http PUT 'http://localhost:8080/core/trip' \
         'Content-Type:application/json;charset=UTF-8' \
    @@ -3363,8 +3511,8 @@ 

    {
       "tripId" : 1,
    -  "startDate" : "2024-05-09",
    -  "endDate" : "2024-05-10",
    +  "startDate" : "2024-05-14",
    +  "endDate" : "2024-05-15",
       "tripName" : "test"
     }
    @@ -3706,8 +3854,8 @@