Skip to content

Commit

Permalink
Merge pull request #105 from Funssion-SWM/develope
Browse files Browse the repository at this point in the history
MVP 2.0
  • Loading branch information
goathoon authored Oct 11, 2023
2 parents 8a353d7 + eb4c058 commit 28324aa
Show file tree
Hide file tree
Showing 30 changed files with 860 additions and 97 deletions.
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
@@ -0,0 +1,15 @@
package Funssion.Inforum.common.exception.etc;

import Funssion.Inforum.common.exception.response.ErrorResult;
import org.springframework.http.HttpStatus;

public class ValueTooLongException extends RuntimeException{
private ErrorResult errorResult;
private String message;

public ValueTooLongException(String message) {
this.message = message;
this.errorResult = new ErrorResult(HttpStatus.INTERNAL_SERVER_ERROR, message);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import Funssion.Inforum.common.exception.etc.DuplicateException;
import Funssion.Inforum.common.exception.etc.ImageIOException;
import Funssion.Inforum.common.exception.etc.UnAuthorizedException;
import Funssion.Inforum.common.exception.etc.ValueTooLongException;
import Funssion.Inforum.common.exception.notfound.NotFoundException;
import Funssion.Inforum.common.exception.response.ErrorResult;
import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.postgresql.util.PSQLException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.validation.FieldError;
Expand Down Expand Up @@ -67,6 +69,13 @@ public Map<String, List<String>> handleValidationEx(MethodArgumentNotValidExcept
public ErrorResult handleDataIntegrityViolationOfJSONB(DataIntegrityViolationException e){
return new ErrorResult(BAD_REQUEST,e.getMessage());
}

@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(ValueTooLongException.class)
public ErrorResult handleDataIntegrityViolationOfJSONB(ValueTooLongException e){
return new ErrorResult(BAD_REQUEST,e.getMessage());
}

@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(TypeMismatchException.class)
public ErrorResult handleTypeMismatchEx (TypeMismatchException e) {
Expand Down Expand Up @@ -101,6 +110,11 @@ public ErrorResult handleDuplicateEx(DuplicateException e){
return e.getErrorResult();
}

@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(PSQLException.class)
public ErrorResult handlePSQLException(PSQLException e){
return new ErrorResult(BAD_REQUEST, "DB exception occurred");
}
@ResponseStatus(INTERNAL_SERVER_ERROR)
@ExceptionHandler(Throwable.class)
public ErrorResult handleGeneralEx(Throwable e) {
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);
}
}
4 changes: 2 additions & 2 deletions src/main/java/Funssion/Inforum/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti
authorizeRequests
.requestMatchers(HttpMethod.OPTIONS, "/**/*").permitAll()
//users 포함한 end point 보안 적용 X
.requestMatchers("/users/**").permitAll()
.requestMatchers(HttpMethod.GET,"/users/**").permitAll()
.requestMatchers(HttpMethod.GET, "/users/profile/**").permitAll() // 개인 정보 수정은 권한 필요
.requestMatchers(HttpMethod.POST, "/users/login").authenticated() //spring security filter에서 redirect
.requestMatchers(HttpMethod.GET,"/tags/**").permitAll()
.requestMatchers("/oauth2/authorization/**").permitAll()
.requestMatchers("/login/oauth2/code/**").permitAll()
.requestMatchers(HttpMethod.GET, "/users/profile/**").permitAll() // 개인 정보 수정은 권한 필요
.requestMatchers("/error/**").permitAll()
.requestMatchers(HttpMethod.GET, "/memos/**").permitAll()
.requestMatchers(HttpMethod.GET,"/questions/**").permitAll()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +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.entity.MemberProfileEntity;
import Funssion.Inforum.domain.member.service.MailService;
import Funssion.Inforum.domain.member.service.MemberService;
import Funssion.Inforum.domain.member.dto.request.PasswordUpdateDto;
import Funssion.Inforum.domain.post.utils.AuthUtils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand All @@ -24,6 +25,7 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
Expand All @@ -45,8 +47,8 @@ public class MemberController {

@PostMapping("")
@ResponseStatus(HttpStatus.CREATED)
public SaveMemberResponseDto create(@RequestBody @Valid MemberSaveDto memberSaveDto){ //dto로 바꿔야함
return memberService.requestMemberRegistration(memberSaveDto);
public SaveMemberResponseDto create(HttpServletRequest request, HttpServletResponse response, @RequestBody @Valid MemberSaveDto memberSaveDto) throws IOException { //dto로 바꿔야함
return memberService.requestMemberRegistration(memberSaveDto,request,response);
}

@PostMapping("/authenticate-email")
Expand Down Expand Up @@ -89,7 +91,6 @@ public IsSuccessResponseDto registerName(@PathVariable("id") String userId,@Requ
@GetMapping("/check")
public ValidMemberDto method(@CurrentSecurityContext SecurityContext context) {
String userId = context.getAuthentication().getName();
log.info("user id = {}",userId);
Long loginId = userId.equals("anonymousUser") ? -1L : Long.valueOf(userId);
boolean isLogin = !userId.equals("anonymousUser");
return new ValidMemberDto(loginId, isLogin);
Expand All @@ -98,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,7 +18,6 @@ public class AuthService implements UserDetailsService {

@Override
public UserDetails loadUserByUsername(String userEmail) throws UsernameNotFoundException {
log.info("useremail = {}",userEmail);
NonSocialMember member = nonSocialMemberRepository.findNonSocialMemberByEmail(userEmail)
.orElseThrow(() -> new UsernameNotFoundException("이 이메일과 매칭되는 유저가 존재하지 않습니다 : " + userEmail));
// non social, social 섞어있기 때문에, user_id를 CustomUserDetail 의 id로 생성합니다. -> 토큰의 getName의 user_id가 들어갑니다.
Expand Down
Loading

0 comments on commit 28324aa

Please sign in to comment.