Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add api withdrawing member #104

Merged
merged 2 commits into from
Oct 10, 2023
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
3 changes: 2 additions & 1 deletion ddl.sql
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ CREATE TABLE member.info (
image_path varchar(300),
created_date timestamp,
follow_cnt int8 not null default 0,
follower_cnt int8 not null default 0
follower_cnt int8 not null default 0,
is_deleted bool not null default false
);

create table comment.info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@
public abstract class SecurityContextUtils {
public static final Long ANONYMOUS_USER_ID = 0L;
public static final String ANONYMOUS_USER_ID_STRING = "0";
public static final String ANONYMOUS_USER_NAME = "anonymousUser";

public static Long getUserId() {
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
if (userId.equals("anonymousUser")) return ANONYMOUS_USER_ID;
if (userId.equals(ANONYMOUS_USER_NAME)) return ANONYMOUS_USER_ID;
return Long.valueOf(userId);
}

public static Long getAuthorizedUserId() {
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
if (userId.equals("anonymousUser")) throw new UnAuthorizedException("인증되지 않은 사용자입니다.");
if (userId.equals(ANONYMOUS_USER_NAME)) throw new UnAuthorizedException("인증되지 않은 사용자입니다.");
return Long.valueOf(userId);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package Funssion.Inforum.domain.member.controller;


import Funssion.Inforum.common.constant.CRUDType;
import Funssion.Inforum.common.dto.IsSuccessResponseDto;
import Funssion.Inforum.common.exception.badrequest.BadRequestException;
import Funssion.Inforum.common.exception.notfound.NotFoundException;
import Funssion.Inforum.common.utils.SecurityContextUtils;
import Funssion.Inforum.domain.member.dto.request.*;
import Funssion.Inforum.domain.member.dto.response.*;
import Funssion.Inforum.domain.member.service.MailService;
import Funssion.Inforum.domain.member.service.MemberService;
import Funssion.Inforum.domain.post.utils.AuthUtils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand Down Expand Up @@ -96,22 +99,14 @@ public ValidMemberDto method(@CurrentSecurityContext SecurityContext context) {
@ResponseStatus(HttpStatus.NO_CONTENT)
@GetMapping("/logout")
public void logout(HttpServletRequest request, HttpServletResponse response) {
AuthUtils.logout(request, response);
}

Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("accessToken".equals(cookie.getName())) {
log.info("[Logout] User Id ={},", cookie.getValue());
}
else if ("refreshToken".equals(cookie.getName())){
log.info("[Logout] refresh token invalidated");
}
}
}
ResponseCookie invalidateAccessCookie = ResponseCookie.from("accessToken", "none").maxAge(0).path("/").domain(".inforum.me").sameSite("none").httpOnly(true).secure(true).build();
ResponseCookie invalidateRefreshCookie = ResponseCookie.from("refreshToken", "none").maxAge(0).path("/").domain(".inforum.me").sameSite("none").httpOnly(true).secure(true).build();
response.addHeader("Set-Cookie", invalidateAccessCookie.toString());
response.addHeader("Set-Cookie",invalidateRefreshCookie.toString());
@PostMapping("/withdraw")
public void withdraw(HttpServletRequest request, HttpServletResponse response) {
Long userId = SecurityContextUtils.getAuthorizedUserId();
memberService.withdrawUser(userId);
AuthUtils.logout(request, response);
}

@PostMapping("/profile/{id}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public MemberProfileEntity(String profileImageFilePath, String nickname, String
this.userTags = userTags;
}

public MemberProfileEntity(String profileImageFilePath, String nickname, String introduce) {
this.profileImageFilePath = profileImageFilePath;
this.nickname = nickname;
this.introduce = introduce;
}

public static RowMapper<MemberProfileEntity> MemberInfoRowMapper() {
return ((rs, rowNum) ->
MemberProfileEntity.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ public interface MemberRepository {
IsSuccessResponseDto findAndChangePassword(PasswordUpdateDto passwordUpdateDto);

String findEmailByAuthCode(String code);

void deleteUser(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public SaveMemberResponseDto save(SocialMember member) {
}

public Optional<NonSocialMember> findNonSocialMemberByEmail(String email) {
String sql ="SELECT A.ID AS A_ID ,U.ID AS U_ID,A.PASSWORD,U.EMAIL,U.FOLLOW_CNT,U.FOLLOWER_CNT FROM member.info AS U JOIN MEMBER.AUTH AS A ON U.ID = A.USER_ID WHERE U.EMAIL = ?";
String sql ="SELECT A.ID AS A_ID ,U.ID AS U_ID,A.PASSWORD,U.EMAIL,U.FOLLOW_CNT,U.FOLLOWER_CNT FROM member.info AS U JOIN MEMBER.AUTH AS A ON U.ID = A.USER_ID WHERE U.IS_DELETED = false AND U.EMAIL = ?";
try{
NonSocialMember nonSocialMember = jdbcTemplate.queryForObject(sql,nonSocialmemberRowMapper(),email);
return Optional.of(nonSocialMember);
Expand All @@ -68,7 +68,7 @@ public Optional<NonSocialMember> findNonSocialMemberByEmail(String email) {
}
}
public Optional<SocialMember> findSocialMemberByEmail(String email){
String sql ="SELECT ID,NAME,EMAIL,LOGIN_TYPE,CREATED_DATE,IMAGE_PATH,INTRODUCE,TAGS,FOLLOW_CNT,FOLLOWER_CNT FROM member.info WHERE EMAIL = ?";
String sql ="SELECT ID,NAME,EMAIL,LOGIN_TYPE,CREATED_DATE,IMAGE_PATH,INTRODUCE,TAGS,FOLLOW_CNT,FOLLOWER_CNT FROM member.info WHERE is_deleted = false and EMAIL = ?";
try{
SocialMember socialMember = jdbcTemplate.queryForObject(sql,socialMemberRowMapper(),email);
return Optional.of(socialMember);
Expand All @@ -80,7 +80,7 @@ public Optional<SocialMember> findSocialMemberByEmail(String email){

@Override
public Optional<Member> findByName(String name) {
String sql ="SELECT ID,EMAIL,NAME FROM member.info WHERE NAME = ?";
String sql ="SELECT ID,EMAIL,NAME FROM member.info WHERE IS_DELETED = false AND NAME = ?";

try{
Member member = jdbcTemplate.queryForObject(sql,memberEmailAndNameRowMapper(),name);
Expand All @@ -102,7 +102,7 @@ public IsSuccessResponseDto saveSocialMemberNickname(String nickname,Long userId

@Override
public String findEmailByNickname(String nickname) {
String sql ="select email from member.info where name = ?";
String sql ="select email from member.info where is_deleted = false and name = ?";
try{
return jdbcTemplate.queryForObject(sql, String.class, nickname);
}catch(EmptyResultDataAccessException e){
Expand Down Expand Up @@ -217,6 +217,15 @@ private SaveMemberResponseDto saveSocialMemberInUserTable(SocialMember member) {
.build();
}

@Override
public void deleteUser(Long userId) {
String sql = "update member.info set is_deleted = true where id = ?";

if (jdbcTemplate.update(sql, userId) != 1) {
throw new BadRequestException("fail in deleting user : userId = " + userId);
}
}

private RowMapper<NonSocialMember> nonSocialmemberRowMapper(){
return new RowMapper<NonSocialMember>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import Funssion.Inforum.domain.post.memo.repository.MemoRepository;
import Funssion.Inforum.domain.post.qna.repository.AnswerRepository;
import Funssion.Inforum.domain.post.qna.repository.QuestionRepository;
import Funssion.Inforum.domain.profile.ProfileRepository;
import Funssion.Inforum.jwt.TokenProvider;
import Funssion.Inforum.s3.S3Repository;
import Funssion.Inforum.s3.S3Utils;
Expand All @@ -32,8 +33,10 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.io.IOException;
import java.util.Optional;
import java.util.UUID;

/* Spring Security 에서 유저의 정보를 가저오기 위한 로직이 포함. */
@Slf4j
Expand All @@ -51,6 +54,7 @@ public class MemberService {
private final CommentRepository commentRepository;
private final S3Repository s3Repository;
private final FollowRepository followRepository;
private final ProfileRepository profileRepository;

@Value("${aws.s3.profile-dir}")
private String profileDir;
Expand Down Expand Up @@ -240,6 +244,14 @@ private IsProfileSavedDto updateProfile(Long userId, MemberProfileEntity memberP
return myRepository.updateProfile(userId, memberProfileEntity);
}

@Transactional
public void withdrawUser(Long userId) {
String anonymousUserName = UUID.randomUUID().toString().substring(0, 15);
profileRepository.updateProfile(userId, new MemberProfileEntity(null, anonymousUserName, "탈퇴한 유저입니다."));
memberRepository.deleteUser(userId);
}


@Transactional(readOnly = true)
public MemberProfileDto getMemberProfile(Long userId){
Long requestUserId = SecurityContextUtils.getUserId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import Funssion.Inforum.domain.member.entity.MemberProfileEntity;
import Funssion.Inforum.domain.post.domain.Post;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

import java.sql.Date;
import java.time.LocalDateTime;

@Getter
@SuperBuilder
public class ReComment extends Post {
private Long parentCommentId;
private String commentText;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package Funssion.Inforum.domain.post.qna;

public class Constant {
public abstract class Constant {
public final static String NONE_MEMO_QUESTION = "0";
}
12 changes: 12 additions & 0 deletions src/main/java/Funssion/Inforum/domain/post/utils/AuthUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import Funssion.Inforum.common.constant.CRUDType;
import Funssion.Inforum.common.utils.SecurityContextUtils;
import Funssion.Inforum.domain.post.memo.exception.NeedAuthenticationException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseCookie;

import static Funssion.Inforum.common.constant.CRUDType.READ;

Expand All @@ -15,4 +19,12 @@ public static Long getUserId(CRUDType type) {

throw new NeedAuthenticationException(type.toString().toLowerCase() + " fail");
}

public static void logout(HttpServletRequest request, HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
ResponseCookie invalidateAccessCookie = ResponseCookie.from("accessToken", "none").maxAge(0).path("/").domain(".inforum.me").sameSite("none").httpOnly(true).secure(true).build();
ResponseCookie invalidateRefreshCookie = ResponseCookie.from("refreshToken", "none").maxAge(0).path("/").domain(".inforum.me").sameSite("none").httpOnly(true).secure(true).build();
response.addHeader("Set-Cookie", invalidateAccessCookie.toString());
response.addHeader("Set-Cookie",invalidateRefreshCookie.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package Funssion.Inforum.domain.profile;

import Funssion.Inforum.domain.member.entity.MemberProfileEntity;
import Funssion.Inforum.domain.tag.repository.TagRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;

@Repository
public class ProfileRepository {

private final JdbcTemplate template;

public ProfileRepository(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}

public void updateProfile(Long userId, MemberProfileEntity memberProfile) {
updateAuthorProfileInMemo(userId, memberProfile);
updateAuthorProfileInComment(userId, memberProfile);
updateAuthorProfileInReComment(userId, memberProfile);
updateAuthorProfileInQuestion(userId, memberProfile);
updateAuthorProfileInAnswer(userId, memberProfile);
updateUserProfile(userId, memberProfile);
}

private void updateAuthorProfileInMemo(Long userId, MemberProfileEntity memberProfile) {
String sql = "update memo.info " +
"set author_image_path = ?, author_name = ? " +
"where author_id = ?";

template.update(sql, memberProfile.getProfileImageFilePath(), memberProfile.getNickname(), userId);
}

private void updateAuthorProfileInComment(Long userId, MemberProfileEntity memberProfile) {
String sql = "update comment.info " +
"set author_image_path = ?, author_name = ? " +
"where author_id = ?";

template.update(sql, memberProfile.getProfileImageFilePath(), memberProfile.getNickname(), userId);
}

private void updateAuthorProfileInReComment(Long userId, MemberProfileEntity memberProfile) {
String sql = "update comment.re_comments " +
"set author_image_path = ?, author_name = ? " +
"where author_id = ?";

template.update(sql, memberProfile.getProfileImageFilePath(), memberProfile.getNickname(), userId);
}

private void updateAuthorProfileInQuestion(Long userId, MemberProfileEntity memberProfile) {
String sql = "update question.info " +
"set author_image_path = ?, author_name = ? " +
"where author_id = ?";

template.update(sql, memberProfile.getProfileImageFilePath(), memberProfile.getNickname(), userId);
}

private void updateAuthorProfileInAnswer(Long userId, MemberProfileEntity memberProfile) {
String sql = "update question.answer " +
"set author_image_path = ?, author_name = ? " +
"where author_id = ?";

template.update(sql, memberProfile.getProfileImageFilePath(), memberProfile.getNickname(), userId);
}

private void updateUserProfile(Long userId, MemberProfileEntity memberProfile) {
String sql = "update member.info " +
"set image_path = ?, name = ?, introduce = ? " +
"where id = ?";

template.update(sql, memberProfile.getProfileImageFilePath(), memberProfile.getNickname(), memberProfile.getIntroduce(), userId);
}
}
Loading