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
13 changes: 10 additions & 3 deletions src/main/java/com/codeit/todo/common/config/JwtTokenProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@
import com.codeit.todo.common.exception.payload.ErrorStatus;
import io.jsonwebtoken.*;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseCookie;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.parameters.P;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.Base64;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Component
@RequiredArgsConstructor
Expand Down Expand Up @@ -91,4 +90,12 @@ public String getUserEmail(String jwtToken) {
}


private final Set<String> tokenBlackList = new HashSet<>();
public void addToBlackList(String currentToken) {
tokenBlackList.add(currentToken);
}

public boolean isTokenBlackListed(String jwtToken){
return tokenBlackList.contains(jwtToken);
}
}
9 changes: 8 additions & 1 deletion src/main/java/com/codeit/todo/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public class User {
@Column(name = "profile_pic", nullable = false)
private String profilePic;

@Column(name = "user_status", nullable = false)
private String userStatus;


@OneToMany(mappedBy= "user", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<Goal> goals = new ArrayList<>();

Expand All @@ -43,12 +47,13 @@ public class User {
private List<Follow> followees = new ArrayList<>();

@Builder
public User(int userId, String name, String email, String password, String profilePic) {
public User(int userId, String name, String email, String password, String profilePic, String userStatus) {
this.userId = userId;
this.name = name;
this.email = email;
this.password = password;
this.profilePic = profilePic;
this.userStatus = userStatus;
}

public void updateProfilePic(String completePicUrl){
Expand All @@ -58,4 +63,6 @@ public void updateProfilePic(String completePicUrl){
public void updatePassword(String password){
this.password = password;
}

public void updateStatus(){this.userStatus = "탈퇴";}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

import com.codeit.todo.domain.Comment;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface CommentRepository extends JpaRepository<Comment, Integer> {

List<Comment> findByUser_UserId(int userId);
}

13 changes: 13 additions & 0 deletions src/main/java/com/codeit/todo/repository/FollowRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import com.codeit.todo.domain.Follow;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

Expand Down Expand Up @@ -31,5 +32,17 @@ public interface FollowRepository extends JpaRepository<Follow, Integer> {
List<Integer> findFolloweeIdsByFollowerId(@Param("userId") int userId);

Optional<Follow> findByFollower_UserIdAndFollowee_UserId(int followerId, int followeeId);

@Modifying
@Query
("DELETE FROM Follow f " +
"WHERE f.followee.userId = :userId ")
void deleteByFolloweeUserId(@Param("userId") int userId);

@Modifying
@Query(
"DELETE FROM Follow f " +
"WHERE f.follower.userId = :userId ")
void deleteByFollowerUserId(@Param("userId") int userId);
}

2 changes: 2 additions & 0 deletions src/main/java/com/codeit/todo/repository/GoalRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

Expand Down Expand Up @@ -40,4 +41,5 @@ public interface GoalRepository extends JpaRepository<Goal, Integer> {
Slice<Goal> findByUserAndHasTodosAfterLastGoalId(@Param("lastGoalId") Integer lastGoalId, @Param("userId") int userId, Pageable pageable, @Param("today") LocalDate today);

List<Goal> findByGoalTitleContains(@Param("keyword") String keyword);

}
3 changes: 3 additions & 0 deletions src/main/java/com/codeit/todo/repository/LikesRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import com.codeit.todo.domain.Likes;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface LikesRepository extends JpaRepository<Likes, Integer> {
Boolean existsByUser_UserIdAndComplete_CompleteId(int userId, int completeId);

Optional<Likes> findByComplete_CompleteIdAndUser_UserId(int completeId, int userId);

List<Likes> findByUser_UserId(int userId);
}
2 changes: 2 additions & 0 deletions src/main/java/com/codeit/todo/service/user/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ public interface UserService {
ReadTargetUserResponse findTargetUserProfile(int userId, int targetUserId);

ReadMyPageResponse findUserInfoAndFollows(int userId);

UpdateUserStatusResponse updateUserStatus(int userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

import com.codeit.todo.common.config.JwtTokenProvider;
import com.codeit.todo.common.exception.ApplicationException;
import com.codeit.todo.common.exception.auth.AuthorizationDeniedException;
import com.codeit.todo.common.exception.payload.ErrorStatus;
import com.codeit.todo.common.exception.user.SignUpException;
import com.codeit.todo.common.exception.user.UpdatePasswordException;
import com.codeit.todo.common.exception.user.UserNotFoundException;
import com.codeit.todo.domain.User;
import com.codeit.todo.repository.FollowRepository;
import com.codeit.todo.repository.GoalRepository;
import com.codeit.todo.repository.UserRepository;
import com.codeit.todo.repository.*;
import com.codeit.todo.service.storage.StorageService;
import com.codeit.todo.service.user.UserService;
import com.codeit.todo.web.dto.request.auth.LoginRequest;
Expand Down Expand Up @@ -37,6 +36,8 @@ public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final GoalRepository goalRepository;
private final FollowRepository followRepository;
private final LikesRepository likesRepository;
private final CommentRepository commentRepository;
private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider;
private final PasswordEncoder passwordEncoder;
Expand Down Expand Up @@ -78,12 +79,16 @@ public String login(LoginRequest loginRequest){
try{
User user = userRepository.findByEmail(email)
.orElseThrow(()-> new UserNotFoundException(email, "User"));
if(user.getUserStatus().equals("탈퇴")) throw new AuthorizationDeniedException("탈퇴한 회원입니다. 로그인 권한이 없습니다.");

Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(email, password));
SecurityContextHolder.getContext().setAuthentication(authentication);

return jwtTokenProvider.createToken(email);
}catch(Exception e){
} catch(AuthorizationDeniedException e){
e.printStackTrace();
throw new AuthorizationDeniedException("탈퇴한 회원입니다. 로그인 권한이 없습니다.");
} catch(Exception e){
e.printStackTrace();
throw new ApplicationException(new ErrorStatus(
"로그인 과정에서 에러 발생",
Expand Down Expand Up @@ -162,6 +167,22 @@ public ReadMyPageResponse findUserInfoAndFollows(int userId) {
return ReadMyPageResponse.from(followerCount, followeeCount);
}

@Transactional
@Override
public UpdateUserStatusResponse updateUserStatus(int userId) {
User user = getUser(userId);
user.updateStatus();

followRepository.deleteByFolloweeUserId(userId);
followRepository.deleteByFollowerUserId(userId);

goalRepository.findByUser_UserId(userId).forEach(goalRepository::delete);
likesRepository.findByUser_UserId(userId).forEach(likesRepository::delete);
commentRepository.findByUser_UserId(userId).forEach(commentRepository::delete);

return UpdateUserStatusResponse.from(userId);
}

public User getUser(int userId){
User user = userRepository.findById(userId)
.orElseThrow(()-> new UserNotFoundException(String.valueOf(userId), "User"));
Expand Down
29 changes: 24 additions & 5 deletions src/main/java/com/codeit/todo/web/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package com.codeit.todo.web.controller;

import com.codeit.todo.common.config.JwtTokenProvider;
import com.codeit.todo.repository.CustomUserDetails;
import com.codeit.todo.service.user.UserService;
import com.codeit.todo.web.dto.request.auth.LoginRequest;
import com.codeit.todo.web.dto.request.auth.SignUpRequest;
import com.codeit.todo.web.dto.request.auth.UpdatePasswordRequest;
import com.codeit.todo.web.dto.request.auth.UpdatePictureRequest;
import com.codeit.todo.web.dto.response.Response;
import com.codeit.todo.web.dto.response.auth.ReadMyPageResponse;
import com.codeit.todo.web.dto.response.auth.ReadTargetUserResponse;
import com.codeit.todo.web.dto.response.auth.UpdatePasswordResponse;
import com.codeit.todo.web.dto.response.auth.UpdatePictureResponse;
import com.codeit.todo.web.dto.response.auth.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -26,7 +26,7 @@
public class AuthController {

private final UserService userService;

private final JwtTokenProvider jwtTokenProvider;
@Operation(summary = "회원가입", description = "이름, 이메일, 비밀번호로 회원가입")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "회원가입 성공")
Expand Down Expand Up @@ -116,4 +116,23 @@ public Response<ReadMyPageResponse> getMyPage(@AuthenticationPrincipal CustomUse
return Response.ok( userService.findUserInfoAndFollows(userId));
}

@Operation(
summary = "회원 탈퇴",
description = "user_status를 '탈퇴'로 변경하고 목표, 할일, 인증, 좋아요, 댓글, 팔로워, 팔로이 모두 삭제"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "탈퇴 성공")
})
@DeleteMapping("/withdrawl")
public Response<UpdateUserStatusResponse> userWithdraw(
HttpServletRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
String currentToken = request.getHeader("token");
jwtTokenProvider.addToBlackList(currentToken);

int userId = userDetails.getUserId();
return Response.ok(userService.updateUserStatus(userId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public User toEntity(String encodedPassword, String profilePic) {
.email(this.email)
.password(encodedPassword)
.profilePic(profilePic)
.userStatus("가입")
.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.codeit.todo.web.dto.response.auth;

import lombok.Builder;

@Builder
public record UpdateUserStatusResponse(int userId) {

public static UpdateUserStatusResponse from(int userId) {
return UpdateUserStatusResponse.builder()
.userId(userId)
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
));
}

if(jwtTokenProvider.isTokenBlackListed(jwtToken)){
log.info("블랙리스트에 추가된 토큰 : {}", jwtToken);
throw new JwtException(ErrorStatus.toErrorStatus(
"블랙리스트에 추가되어 있는 토큰입니다.", 401

));
}

log.info("토큰이 인식되었습니다. : {}", jwtToken);
if (jwtTokenProvider.validToken(jwtToken)) {
log.info("토큰이 유효합니다. : {}", jwtToken);
Expand Down
Loading