Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/main/java/com/recipe/app/src/common/config/JwtFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ public class JwtFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

System.out.println(jwtUtil.createAccessToken(18L));

String accessToken = jwtUtil.resolveAccessToken((HttpServletRequest) request);
String requestURI = ((HttpServletRequest) request).getRequestURI();

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/recipe/app/src/common/entity/BaseEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,15 @@ public abstract class BaseEntity {
@Column(name = "updatedAt", nullable = false)
private LocalDateTime updatedAt = LocalDateTime.now();

@Column(name = "deletedAt")
private LocalDateTime deletedAt;

public void markAsDeleted() {
this.deletedAt = LocalDateTime.now();
}

public boolean isDeleted() {
return this.deletedAt != null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@ public IngredientCreateResponse create(Long userId, IngredientRequest request) {
return new IngredientCreateResponse(ingredient.getIngredientId());
}

@Transactional
public void deleteAllByUserId(long userId) {

List<Ingredient> ingredients = ingredientRepository.findByUserId(userId);

ingredientRepository.deleteAll(ingredients);
}

@Transactional(readOnly = true)
public Ingredient findByIngredientId(Long ingredientId) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,6 @@ private Recipe findByUserIdAndRecipeId(User user, Long recipeId) {
});
}

@Transactional
public void deleteAllByUserId(long userId) {

List<Recipe> recipes = recipeRepository.findByUserId(userId);

recipeScrapService.deleteAllByUserId(userId);
recipeViewService.deleteAllByUserId(userId);
recipeRepository.deleteAll(recipes);
}

@Transactional(readOnly = true)
public long countRecipeScrapByUserId(long userId) {

Expand Down
8 changes: 6 additions & 2 deletions src/main/java/com/recipe/app/src/user/api/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.recipe.app.src.user.application.dto.UserSocialLoginResponse;
import com.recipe.app.src.user.application.dto.UserTokenRefreshRequest;
import com.recipe.app.src.user.application.dto.UserTokenRefreshResponse;
import com.recipe.app.src.user.application.dto.UserWithdrawRequest;
import com.recipe.app.src.user.domain.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand Down Expand Up @@ -106,9 +107,12 @@ public void patchUser(@Parameter(hidden = true) User user,
@Operation(summary = "회원 탈퇴 API")
@DeleteMapping
@LoginCheck
public void deleteUser(HttpServletRequest request, @Parameter(hidden = true) User user) {
public void deleteUser(HttpServletRequest request,
@Parameter(hidden = true) User user,
@Parameter(name = "회원 탈퇴 요청 정보")
@RequestBody(required = false) UserWithdrawRequest withdrawRequest) {

userFacadeService.deleteUser(user, request);
userFacadeService.deleteUser(user, request, withdrawRequest);
}

@Operation(summary = "로그아웃 API")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
import com.recipe.app.src.fridge.application.FridgeService;
import com.recipe.app.src.fridgeBasket.application.FridgeBasketService;
import com.recipe.app.src.ingredient.application.IngredientService;
import com.recipe.app.src.recipe.application.RecipeScrapService;
import com.recipe.app.src.recipe.application.RecipeSearchService;
import com.recipe.app.src.recipe.application.RecipeService;
import com.recipe.app.src.recipe.application.RecipeViewService;
import com.recipe.app.src.recipe.application.blog.BlogScrapService;
import com.recipe.app.src.recipe.application.blog.BlogViewService;
import com.recipe.app.src.recipe.application.youtube.YoutubeScrapService;
import com.recipe.app.src.recipe.application.youtube.YoutubeViewService;
import com.recipe.app.src.recipe.domain.Recipe;
import com.recipe.app.src.user.application.dto.UserProfileResponse;
import com.recipe.app.src.user.application.dto.UserWithdrawRequest;
import com.recipe.app.src.user.domain.User;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
Expand All @@ -24,6 +27,8 @@ public class UserFacadeService {
private final UserService userService;
private final RecipeService recipeService;
private final RecipeSearchService recipeSearchService;
private final RecipeScrapService recipeScrapService;
private final RecipeViewService recipeViewService;
private final YoutubeScrapService youtubeScrapService;
private final YoutubeViewService youtubeViewService;
private final BlogScrapService blogScrapService;
Expand All @@ -35,13 +40,16 @@ public class UserFacadeService {
private static final int USER_PROFILE_RECIPE_CNT = 6;

public UserFacadeService(UserService userService, RecipeService recipeService, RecipeSearchService recipeSearchService,
RecipeScrapService recipeScrapService, RecipeViewService recipeViewService,
YoutubeScrapService youtubeScrapService, YoutubeViewService youtubeViewService,
BlogScrapService blogScrapService, BlogViewService blogViewService,
FridgeService fridgeService, FridgeBasketService fridgeBasketService, IngredientService ingredientService) {

this.userService = userService;
this.recipeService = recipeService;
this.recipeSearchService = recipeSearchService;
this.recipeScrapService = recipeScrapService;
this.recipeViewService = recipeViewService;
this.youtubeScrapService = youtubeScrapService;
this.youtubeViewService = youtubeViewService;
this.blogScrapService = blogScrapService;
Expand All @@ -64,17 +72,17 @@ public UserProfileResponse findUserProfile(User user) {
}

@Transactional
public void deleteUser(User user, HttpServletRequest request) {
public void deleteUser(User user, HttpServletRequest request, UserWithdrawRequest withdrawRequest) {

fridgeService.deleteAllByUserId(user.getUserId());
fridgeBasketService.deleteAllByUserId(user.getUserId());
recipeService.deleteAllByUserId(user.getUserId());
ingredientService.deleteAllByUserId(user.getUserId());
recipeScrapService.deleteAllByUserId(user.getUserId());
recipeViewService.deleteAllByUserId(user.getUserId());
youtubeScrapService.deleteAllByUserId(user.getUserId());
youtubeViewService.deleteAllByUserId(user.getUserId());
blogScrapService.deleteAllByUserId(user.getUserId());
blogViewService.deleteAllByUserId(user.getUserId());

userService.withdraw(user, request);
userService.withdraw(user, request, withdrawRequest);
}
}
16 changes: 13 additions & 3 deletions src/main/java/com/recipe/app/src/user/application/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.recipe.app.src.user.application.dto.UserSocialLoginResponse;
import com.recipe.app.src.user.application.dto.UserTokenRefreshRequest;
import com.recipe.app.src.user.application.dto.UserTokenRefreshResponse;
import com.recipe.app.src.user.application.dto.UserWithdrawRequest;
import com.recipe.app.src.user.domain.User;
import com.recipe.app.src.user.exception.NotFoundUserException;
import com.recipe.app.src.user.exception.UserTokenNotExistException;
Expand All @@ -30,12 +31,15 @@ public class UserService {
private final JwtUtil jwtUtil;
private final BadWordFiltering badWordFiltering;
private final UserAuthClientService userAuthClientService;
private final UserWithdrawalService userWithdrawalService;

public UserService(UserRepository userRepository, JwtUtil jwtUtil, BadWordFiltering badWordFiltering, UserAuthClientService userAuthClientService) {
public UserService(UserRepository userRepository, JwtUtil jwtUtil, BadWordFiltering badWordFiltering,
UserAuthClientService userAuthClientService, UserWithdrawalService userWithdrawalService) {
this.userRepository = userRepository;
this.jwtUtil = jwtUtil;
this.badWordFiltering = badWordFiltering;
this.userAuthClientService = userAuthClientService;
this.userWithdrawalService = userWithdrawalService;
}

@Transactional(readOnly = true)
Expand Down Expand Up @@ -127,11 +131,17 @@ public void update(User user, UserProfileRequest request) {
}

@Transactional
public void withdraw(User user, HttpServletRequest request) {
public void withdraw(User user, HttpServletRequest request, UserWithdrawRequest withdrawRequest) {

userRepository.delete(user);
user.maskPersonalInfo();
user.markAsDeleted();
userRepository.save(user);

logout(request);

if (withdrawRequest != null && StringUtils.hasText(withdrawRequest.getWithdrawalReason())) {
userWithdrawalService.saveWithdrawalReason(user.getUserId(), withdrawRequest.getWithdrawalReason());
}
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.recipe.app.src.user.application;

import com.recipe.app.src.user.domain.UserWithdrawal;
import com.recipe.app.src.user.infra.UserWithdrawalRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserWithdrawalService {

private final UserWithdrawalRepository userWithdrawalRepository;

public UserWithdrawalService(UserWithdrawalRepository userWithdrawalRepository) {
this.userWithdrawalRepository = userWithdrawalRepository;
}

@Transactional
public void saveWithdrawalReason(Long userId, String withdrawalReason) {

UserWithdrawal userWithdrawal = UserWithdrawal.builder()
.userId(userId)
.withdrawalReason(withdrawalReason)
.build();

userWithdrawalRepository.save(userWithdrawal);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.recipe.app.src.user.application.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class UserWithdrawRequest {

private String withdrawalReason;
}
8 changes: 8 additions & 0 deletions src/main/java/com/recipe/app/src/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,12 @@ public void changeDeviceToken(String deviceToken) {

this.deviceToken = deviceToken;
}

public void maskPersonalInfo() {
this.email = null;
this.phoneNumber = null;
this.nickname = "탈퇴한 사용자";
this.profileImgUrl = ProfileImage.getInitProfileImgUrl();
this.deviceToken = null;
}
}
42 changes: 42 additions & 0 deletions src/main/java/com/recipe/app/src/user/domain/UserWithdrawal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.recipe.app.src.user.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "UserWithdrawal")
public class UserWithdrawal {

@Id
@Column(name = "userWithdrawalId", nullable = false, updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userWithdrawalId;

@Column(name = "userId", nullable = false)
private Long userId;

@Column(name = "withdrawalReason", length = 200)
private String withdrawalReason;

@Column(name = "createdAt", nullable = false, updatable = false)
private LocalDateTime createdAt = LocalDateTime.now();

@Builder
public UserWithdrawal(Long userId, String withdrawalReason) {
this.userId = userId;
this.withdrawalReason = withdrawalReason;
this.createdAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.recipe.app.src.user.infra;

import com.recipe.app.src.user.domain.UserWithdrawal;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserWithdrawalRepository extends JpaRepository<UserWithdrawal, Integer> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,36 +121,6 @@ class IngredientServiceTest extends Specification {
result.ingredientId == ingredient.ingredientId
}

def "특정 유저의 재료 목록 제거"() {

given:
Long userId = 1
List<Ingredient> ingredients = [
Ingredient.builder()
.ingredientId(1)
.ingredientCategoryId(1)
.ingredientName("재료1")
.ingredientIconId(1)
.userId(1)
.build(),
Ingredient.builder()
.ingredientId(2)
.ingredientCategoryId(2)
.ingredientName("재료2")
.ingredientIconId(1)
.userId(1)
.build()
]

ingredientRepository.findByUserId(userId) >> ingredients

when:
ingredientService.deleteAllByUserId(userId)

then:
1 * ingredientRepository.deleteAll(ingredients)
}

def "아이디로 재료 조회"() {

given:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,39 +535,6 @@ class RecipeServiceTest extends Specification {
e.message == "레시피 정보를 찾지 못하였습니다."
}

def "특정 유저의 레시피 목록 삭제"() {

given:
Long userId = 1

List<Recipe> recipes = [
Recipe.builder()
.recipeNm("제목")
.introduction("테스트설명")
.level(RecipeLevel.NORMAL)
.userId(1)
.isHidden(false)
.build(),
Recipe.builder()
.recipeNm("제목")
.introduction("설명")
.level(RecipeLevel.NORMAL)
.userId(2)
.isHidden(true)
.build(),
]

recipeRepository.findByUserId(userId) >> recipes

when:
recipeService.deleteAllByUserId(userId)

then:
1 * recipeScrapService.deleteAllByUserId(userId)
1 * recipeViewService.deleteAllByUserId(userId)
1 * recipeRepository.deleteAll(recipes)
}

def "특정 유저의 레시피 스크랩 수 조회"() {

given:
Expand Down
Loading
Loading