-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* [feat] : Security Config 작성 * [feat] : member Repository 추가 * [feat] : Oauth2UserSerivce 구현 - Provider로부터 획득한 유저 정보 처리 Service 구현 * [feat] : AuthErrorCode 구현 * [feat] : 인증 객체 Dto 추가 - 인증 객체 Custom Dto 추가 - AuthDto.class, CustomOauth2User.class * [feat] : Oauth2UserInfo Mapping 객체 구현 - 네이버 소셜로그인 도입을 고려한 Oauth2Response interface 구현 - 카카오 소셜로그인을 위한 Oauth2Response 구현체 KakaoResponse 구현 * [style] : AuthDto 네이밍 변경으로 인한 수정 * [feat] : socialEmail update method 추가 * [feat] : Member Repository 추가 - socialEmail로 회원을 찾는 쿼리 메서드 구현 * [test] : member socialEmail udpate method 테스트 구현 * [test] : memberRepository.findBySocialEmail() 테스트 구현 * [feat] : CustomOauth2User 구현 - Custom Authentication 객체 구현 * [refactor] : Provider로부터 획득한 유저 정보 처리 Service 리팩토링 - 신규 유저 또는 기존 유저 구분 후 저장 또는 업데이트 로직 메서드 추출 - 단일 책임 원칙(SRP)를 위한 책임 분배(createSocialName(), createMemberFromOauth2Response()) - MemberRepository.findBySocialEmail() return Type 변경(Member -> Optional<Member>) * [feat] MemberService.class 추가 * [test] : 쿼리메서드 타입 변경으로 인한 테스트 코드 수정 * [feat] : 회원 구분 객체 Auth 엔티티 추가 * [feat] : AuthRepository 추가 - Member로 Auth 찾는 쿼리 메서드 추가 * [feat] AuthService 추가 - Auth 저장 또는 업데이트 메서드 구현 - 기존 회원 구분 메서드 구현 * [feat] : AuthErrorCode 에러코드 추가 * [feat] : Auth 객체 저장 또는 업데이트 로직 추가 * [feat] : SocialName 필드에서 Provider 추출 메서드 구현 * [feat] : OauthLogin 성공 핸들러 추가 - 회원 구분하여 신규 회원일시 추가 정보 기입 페이지로 리다이렉트 구현 * [refactor] : 단일 책임 원칙 준수하기 위한 메서드 이동 - saveOrUpdate(Oauth2Response oauth2Response) : CustomeOauth2userService.class -> MemberService.class * [fix] : Auth 생성 시 연관된 회원 주입 * [fix] : 오탈자로 인한 오류 해결 - KAKKOA -> KAKAO 수정 * [feat] : MemberErrorCode 추가 * [feat] : AuthController 추가 - kakao login api 구현 * [fix] : 회원 검색 실패 시 예외 추가 * [fix] : provider명 변경 * [fix] : Kakao Login Api 명세와 일치되도록 수정 * [test] : AuthService UnitTest 구현 * [test] : MemberService UnitTest 구현 * [fix] : Enum 필드 수정 - 문자열 저장을 위한 어노테이션 @Enumerated(STRING) 추가 - 컬럼 설정 관련 어노테이션 @column() 추가 * [fix] : 소셜이름 메서드 로직 중 문자 포맷팅 오탈자 수정 * [fix] : 소셜 이름 변경으로 인한 문제 발생 차단을 위한 수정 - 기존 소셜이름(소셜 정보 + 소셜이름) -> default 소셜이름 변경 - default 소셜이메일 -> 소셜 정보 + 소셜이메일 변경 - createSocialName(), createAuth(), parseProviderFromSocialEmail(), etc.. socialName -> socialEmail 변경 * [test] : 소셜 이름 -> 소셜 이메일 로직으로 변경으로 인한 테스트 코드 수정 * [fix] 신규 회원 DB 저장 로직 변경 - Member nickname, job_group, job_category, official_email 제약조건 수정(nullable = false -> true) - 신규 회원 DB저장 시 소셜 정보와 크레딧만 저장, 추가정보는 /additional-info를 통해 insert * [feat] : Member 공무원 이메일 여부를 통한 Auth 상태 변경 추가 * [test] : 공무원 이메일 여부 통한 Auth 상태 변경 단위 테스트 추가 - 공무원 이메일 존재여부 체크 단위테스트 추가 - 공무원 이메일 존재여부에 따른 Auth.status 변경 단위테스트 추가 * [feat] : 닉네임 중복 Api 구현 * [test] : 중복 닉네임 검증 단위테스트 작성 * [feat] : 신규 회원 추가 정보 입력을 통한 회원가입 구현 - 추가 정보 입력을 통한 회원가입 api 구현 - 추가 정보 요청 dto, 회원가입 성공 응답 dto 추가 - 신규 회원 정보 업데이트 및 회원가입 로직 추가 - 신규 회원 관련 에러코드 추가 * [test] : MemberService 회원가입 UnitTest 작성 * [feat] : method 단위 읽기전용 트랜잭션 부여 * [test] : Member UnitTest 추가 - 추가 정보 업데이트 UnitTest 추가 - 소셜이메일 업데이트 UnitTest명 변경 * [rename] : security 관련 클래스 파일 경로 수정 * [style]: 코드 포맷팅 * [chore] jwt 라이브러리 추가 * [feat] : 소셜로그인 성공 이후 로직 구현 - 토큰 발급 후 헤더 설정 및 리다이렉션 구현 - 클래스 네이밍 변경(CustomOauth2AuthenticationSuccessHandler -> CustomOauth2SuccessHandler) * [feat] 소셜 로그인 실패 핸들러 추가 * [feat] : 인증 오류 EntryPoint 추가 * [feat] : Jwt 관련 예외 클래스 추가 * [feat] : jwt Provider 구현 - 타입에 따른 토큰 생성 구현 - 토큰 파싱 구현 - 토큰 검증 구현 * [feat] : 토큰 서비스 추가 * [feat] : jwt 검증 필터 구현 * [feat] : 토큰 예외처리 필터 구현 * [feat] : SecuritConfig 설정 추가 - WebSecurityCustomizer 빈 등록으로 특정 경로 보안 필터 우회 설정 - permitAll 경로 추가 - oauth2Login 실패 핸들러 추가 - 토큰 필터 추가 및 예외 EntiryPoint 추가 * [test] : tokenProvider 단위 테스트 작성 * [chore] : jwt 관련 라이브러리 추가 * [fix] : 회원가입 임시토큰 관련 로직 삭제 * [test] : 회원가입 임시토큰 발급 테스트 코드 삭제 * [style] 코드 포맷팅 * [refactor] : 정적 팩토리 메서드 추가 리펙토링 * [rename] : 패키지 네이밍 변경 * [test] : 정적 팩토리 메서드, 클래스 네이밍 변경으로 인한 리팩토링 * [rename] : AuthDto -> AuthInfo 클래스 네이밍 변경 - AuthDto 클래스 네이밍 변경 - 패키지 구조 변경 auth.dto -> security.oauth2 * [style] Repository 코드 통일성을 위한 어노테이션 삭제 * [refactor] 변경 감지로 인한 불필요한 반환타입 제거 * [test] : 변경 감지에 따른 반환타입 제거로 인한 테스트 로직 수정 * [feat] : Member 외래키 제거 * [refactor] 변경 감지로 인한 불필요한 반환타입 제거 * [fix] : 회원가입 응답DTO 필드 변경 * [test] : 변경 감지에 따른 반환타입 제거로 인한 테스트 로직 수정 * [rename] : 클래스명 및 필드명 수정 * [test] : 레코드 필드명 수정에 따른 수정 * [style] : import 클래스명 변경 * [feat] : requestDto validation 추가 * [rename] : enum 필드명 통일을 위한 네이밍 수정 * [refactor] : 가독성을 위한 static import enum타입 제거 * [test] : 가독성을 위한 static import enum타입 제거 * [rename] : enum 에러코드 네이밍 수정 * [feat] : requestMapping 추가 * [feat] : 추가정보 api 인증/인가 허용 * [sytle] : 안쓰는 의존 코드 삭제 * [feat] : 소셜이메일로 회원 찾는 메서드 추가 * [fix] : CustomOauth2User 객체가 아닌 Member 객체를 인증 객채로 생성되도록 변경 * [test] : CI test 오류로 인한 테스트 disable 처리 * [test] : 주입 클래스, 변수 순서 변경 * [test] : mock 테스트 명시를 위한 어노테이션 수정 * [refactor] : AuthInfo of() Builder를 이용한 객체 생성 변경 * [feat] : 모든 필드 값을 주입하여 생성하는 팩터리 메서드 추가 * [test] : Member 관련 test를 위한 MemberFixture 추가 * [test] : API 테스트를 위한 인증 객체 setUp 추가 * [feat] Auth 도메인 로딩 전략 변경 - Auth - Member 로딩 전략 변경(Eager -> Lazy) - 가독성을 위한 static import 제거 * [test] : 통합 테스트용 추상메서드 상속
- Loading branch information
Showing
40 changed files
with
1,580 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
src/main/java/com/dnd/gongmuin/auth/cotroller/AuthController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.dnd.gongmuin.auth.cotroller; | ||
|
||
import java.net.URI; | ||
|
||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/auth") | ||
public class AuthController { | ||
|
||
@GetMapping("signin/kakao") | ||
public ResponseEntity<?> kakaoLoginRedirect() { | ||
HttpHeaders httpHeaders = new HttpHeaders(); | ||
// 카카오 로그인 페이지로 리다이렉트 | ||
httpHeaders.setLocation(URI.create("/oauth2/authorization/kakao")); | ||
return new ResponseEntity<>(httpHeaders, HttpStatus.MOVED_PERMANENTLY); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.dnd.gongmuin.auth.domain; | ||
|
||
import static jakarta.persistence.ConstraintMode.*; | ||
|
||
import com.dnd.gongmuin.member.domain.Member; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.EnumType; | ||
import jakarta.persistence.Enumerated; | ||
import jakarta.persistence.FetchType; | ||
import jakarta.persistence.ForeignKey; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.JoinColumn; | ||
import jakarta.persistence.OneToOne; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@Getter | ||
public class Auth { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Enumerated(EnumType.STRING) | ||
@Column(name = "provider", nullable = false) | ||
private Provider provider; | ||
|
||
@Enumerated(EnumType.STRING) | ||
@Column(name = "status", nullable = false) | ||
private AuthStatus status; | ||
|
||
@OneToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "member_id", | ||
nullable = false, | ||
foreignKey = @ForeignKey(NO_CONSTRAINT)) | ||
private Member member; | ||
|
||
@Builder | ||
private Auth(Provider provider, AuthStatus status, Member member) { | ||
this.provider = provider; | ||
this.status = status; | ||
this.member = member; | ||
} | ||
|
||
public static Auth of(Provider provider, AuthStatus status, Member member) { | ||
return Auth.builder() | ||
.provider(provider) | ||
.status(status) | ||
.member(member) | ||
.build(); | ||
} | ||
|
||
public void updateStatus() { | ||
this.status = AuthStatus.OLD; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/dnd/gongmuin/auth/domain/AuthStatus.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.dnd.gongmuin.auth.domain; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public enum AuthStatus { | ||
|
||
NEW("신규"), | ||
OLD("기존"); | ||
|
||
private final String label; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.dnd.gongmuin.auth.domain; | ||
|
||
import java.util.Arrays; | ||
|
||
import com.dnd.gongmuin.auth.exception.AuthErrorCode; | ||
import com.dnd.gongmuin.common.exception.runtime.NotFoundException; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public enum Provider { | ||
|
||
KAKAO("kakao"), | ||
NAVER("naver"); | ||
|
||
private final String provider; | ||
|
||
public static Provider fromProviderName(String providerName) { | ||
return Arrays.stream(values()) | ||
.filter(provider -> provider.getProvider().equalsIgnoreCase(providerName)) | ||
.findFirst() | ||
.orElseThrow(() -> new NotFoundException(AuthErrorCode.NOT_FOUND_PROVIDER)); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/dnd/gongmuin/auth/exception/AuthErrorCode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.dnd.gongmuin.auth.exception; | ||
|
||
import com.dnd.gongmuin.common.exception.ErrorCode; | ||
|
||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public enum AuthErrorCode implements ErrorCode { | ||
|
||
UNSUPPORTED_SOCIAL_LOGIN("해당 소셜 로그인은 지원되지 않습니다.", "AUHT_001"), | ||
NOT_FOUND_PROVIDER("알맞은 Provider를 찾을 수 없습니다.", "AUTH_002"), | ||
NOT_FOUND_AUTH("회원의 AUTH를 찾을 수 없습니다.", "AUTH_003"); | ||
|
||
private final String message; | ||
private final String code; | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/dnd/gongmuin/auth/repository/AuthRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.dnd.gongmuin.auth.repository; | ||
|
||
import java.util.Optional; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import com.dnd.gongmuin.auth.domain.Auth; | ||
import com.dnd.gongmuin.member.domain.Member; | ||
|
||
public interface AuthRepository extends JpaRepository<Auth, Long> { | ||
|
||
Optional<Auth> findByMember(Member member); | ||
} |
52 changes: 52 additions & 0 deletions
52
src/main/java/com/dnd/gongmuin/auth/service/AuthService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.dnd.gongmuin.auth.service; | ||
|
||
import java.util.Objects; | ||
|
||
import org.springframework.stereotype.Service; | ||
|
||
import com.dnd.gongmuin.auth.domain.Auth; | ||
import com.dnd.gongmuin.auth.domain.AuthStatus; | ||
import com.dnd.gongmuin.auth.domain.Provider; | ||
import com.dnd.gongmuin.auth.exception.AuthErrorCode; | ||
import com.dnd.gongmuin.auth.repository.AuthRepository; | ||
import com.dnd.gongmuin.common.exception.runtime.NotFoundException; | ||
import com.dnd.gongmuin.member.domain.Member; | ||
import com.dnd.gongmuin.member.service.MemberService; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class AuthService { | ||
|
||
private final AuthRepository authRepository; | ||
private final MemberService memberService; | ||
|
||
public void saveOrUpdate(Member savedMember) { | ||
Auth findedOrCreatedAuth = authRepository.findByMember(savedMember) | ||
.map(auth -> { | ||
if (!memberService.isOfficialEmail(savedMember)) { | ||
auth.updateStatus(); | ||
} | ||
return auth; | ||
}) | ||
.orElse(createAuth(savedMember)); | ||
|
||
authRepository.save(findedOrCreatedAuth); | ||
} | ||
|
||
public boolean isAuthStatusOld(Member member) { | ||
Auth findAuth = authRepository.findByMember(member) | ||
.orElseThrow(() -> new NotFoundException(AuthErrorCode.NOT_FOUND_AUTH)); | ||
|
||
return Objects.equals(findAuth.getStatus(), AuthStatus.OLD); | ||
} | ||
|
||
private Auth createAuth(Member savedMember) { | ||
String providerName = memberService.parseProviderFromSocialEmail(savedMember); | ||
Provider provider = Provider.fromProviderName(providerName); | ||
|
||
return Auth.of(provider, AuthStatus.NEW, savedMember); | ||
} | ||
|
||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/com/dnd/gongmuin/common/exception/runtime/CustomJwtException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.dnd.gongmuin.common.exception.runtime; | ||
|
||
import com.dnd.gongmuin.common.exception.ErrorCode; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class CustomJwtException extends RuntimeException { | ||
|
||
private final String code; | ||
|
||
public CustomJwtException(ErrorCode errorCode) { | ||
super(errorCode.getMessage()); | ||
this.code = errorCode.getCode(); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
src/main/java/com/dnd/gongmuin/member/controller/MemberController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.dnd.gongmuin.member.controller; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import com.dnd.gongmuin.member.dto.request.AdditionalInfoRequest; | ||
import com.dnd.gongmuin.member.dto.request.ValidateNickNameRequest; | ||
import com.dnd.gongmuin.member.dto.response.SignUpResponse; | ||
import com.dnd.gongmuin.member.dto.response.ValidateNickNameResponse; | ||
import com.dnd.gongmuin.member.service.MemberService; | ||
import com.dnd.gongmuin.security.oauth2.CustomOauth2User; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/auth") | ||
public class MemberController { | ||
|
||
private final MemberService memberService; | ||
|
||
@PostMapping("/check-nickname") | ||
public ResponseEntity<ValidateNickNameResponse> checkNickName( | ||
@RequestBody ValidateNickNameRequest validateNickNameRequest) { | ||
return ResponseEntity.ok(memberService.isDuplicatedNickname(validateNickNameRequest)); | ||
} | ||
|
||
@PostMapping("/member") | ||
public ResponseEntity<SignUpResponse> signUp(@RequestBody AdditionalInfoRequest request, | ||
@AuthenticationPrincipal CustomOauth2User loginMember) { | ||
SignUpResponse response = memberService.signUp(request, loginMember.getEmail()); | ||
|
||
return ResponseEntity.ok(response); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/main/java/com/dnd/gongmuin/member/dto/request/AdditionalInfoRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.dnd.gongmuin.member.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Size; | ||
|
||
public record AdditionalInfoRequest( | ||
|
||
@NotBlank(message = "공무원 이메일은 필수 입력 항목입니다.") | ||
String officialEmail, | ||
@NotBlank(message = "닉네임은 필수 입력 항목입니다.") | ||
@Size(min = 2, max = 12, message = "닉네임은 최소 2자리 이상 최대 12자 이하입니다.") | ||
String nickname, | ||
@NotBlank(message = "직군은 필수 입력 항목입니다.") | ||
String jobGroup, | ||
@NotBlank(message = "직렬은 필수 입력 항목입니다.") | ||
String jobCategory | ||
) { | ||
} |
Oops, something went wrong.