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
17 changes: 16 additions & 1 deletion src/main/java/com/divary/domain/member/entity/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,22 @@
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = {"socialId", "socialType"})
})
public class Member extends BaseEntity {


@Column(nullable = false, unique = true)
private String email;

@Column(nullable = true)
private String socialId; // Apple sub ๋˜๋Š” Google sub

@Enumerated(EnumType.STRING)
@Column(nullable = true)
private SocialType socialType; // APPLE, GOOGLE ๋“ฑ

@Enumerated(EnumType.STRING)
@NotNull
private Role role;
Expand Down Expand Up @@ -61,5 +71,10 @@ public void cancelDeletion() {
public void updateGroup(String newGroup){
this.memberGroup = newGroup;
}


// ์†Œ์…œ ์ •๋ณด ์—…๋ฐ์ดํŠธ (๊ธฐ์กด ํšŒ์› ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์šฉ)
public void updateSocialInfo(String socialId, SocialType socialType) {
this.socialId = socialId;
this.socialType = socialType;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.divary.domain.member.repository;

import com.divary.common.enums.SocialType;
import com.divary.domain.member.entity.Member;
import com.divary.domain.member.enums.Status;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -11,5 +12,6 @@
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByEmail(String email);
Optional<Member> findById(Long id);
Optional<Member> findBySocialIdAndSocialType(String socialId, SocialType socialType);
List<Member> findByStatusAndDeactivatedAtBefore(Status status, LocalDateTime cutoffDate);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.divary.domain.member.service;

import com.divary.common.enums.SocialType;
import com.divary.domain.member.dto.requestDTO.MyPageGroupRequestDTO;
import com.divary.domain.member.dto.response.MyPageImageResponseDTO;
import com.divary.domain.member.dto.response.MyPageProfileResponseDTO;
Expand All @@ -16,7 +17,7 @@ public interface MemberService {
MyPageImageResponseDTO uploadLicense(MultipartFile image, Long userId);
DeactivateResponse requestToDeleteMember(Long memberId);
void cancelDeleteMember(Long memberId);
public Member findOrCreateMember(String email);
Member findOrCreateMemberBySocialId(String socialId, SocialType socialType, String email);

void updateGroup(Long userId, MyPageGroupRequestDTO requestDTO);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.divary.domain.member.service;

import com.divary.common.enums.SocialType;
import com.divary.common.util.EnumValidator;
import com.divary.domain.image.dto.request.ImageUploadRequest;
import com.divary.domain.image.dto.response.ImageResponse;
Expand Down Expand Up @@ -135,19 +136,56 @@ public void cancelDeleteMember(Long memberId) {
}
@Override
@Transactional
public Member findOrCreateMember(String email) {
// 1. Optional์„ ์‚ฌ์šฉํ•˜์—ฌ ํšŒ์›์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
Optional<Member> optionalMember = memberRepository.findByEmail(email);

// 2. ํšŒ์›์ด ์กด์žฌํ•˜๋ฉด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ €์žฅํ•œ ๋’ค ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
return optionalMember.orElseGet(() -> {
Member newMember = Member.builder()
.email(email)
.status(Status.ACTIVE)
.role(Role.USER)
.build();
return memberRepository.save(newMember);
});
public Member findOrCreateMemberBySocialId(String socialId, SocialType socialType, String email) {
// 1. socialId์™€ socialType์œผ๋กœ ํšŒ์› ์กฐํšŒ
Optional<Member> optionalMember = memberRepository.findBySocialIdAndSocialType(socialId, socialType);

// 2. ํšŒ์›์ด ์กด์žฌํ•˜๋ฉด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
if (optionalMember.isPresent()) {
return optionalMember.get();
}

// 3. ๊ธฐ์กด ํšŒ์› ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜: email๋กœ ๊ธฐ์กด ํšŒ์› ์ฐพ๊ธฐ
if (email != null && !email.isEmpty()) {
Optional<Member> existingMember = memberRepository.findByEmail(email);
if (existingMember.isPresent()) {
Member member = existingMember.get();

// 3-1. ๊ธฐ์กด ํšŒ์›์˜ socialId๊ฐ€ ์—†์œผ๋ฉด ์—…๋ฐ์ดํŠธ (๋งˆ์ด๊ทธ๋ ˆ์ด์…˜)
if (member.getSocialId() == null) {
member.updateSocialInfo(socialId, socialType);
return member; // JPA dirty checking์œผ๋กœ ์ž๋™ ์ €์žฅ
}

// 3-2. ์ด๋ฏธ ๋‹ค๋ฅธ ์†Œ์…œ ํƒ€์ž…์œผ๋กœ ๊ฐ€์ž…๋œ ๊ฒฝ์šฐ
if (!member.getSocialType().equals(socialType)) {
throw new BusinessException(
ErrorCode.ALREADY_REGISTERED_WITH_DIFFERENT_SOCIAL,
"์ด ์ด๋ฉ”์ผ์€ ์ด๋ฏธ " + member.getSocialType() + " ๊ณ„์ •์œผ๋กœ ๊ฐ€์ž…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. " +
member.getSocialType() + " ๋กœ๊ทธ์ธ์„ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”."
);
}

// 3-3. ๊ฐ™์€ ์†Œ์…œ ํƒ€์ž…์ธ๋ฐ ๋‹ค๋ฅธ socialId์ธ ๊ฒฝ์šฐ (๋น„์ •์ƒ ์ผ€์ด์Šค)
throw new BusinessException(ErrorCode.INVALID_TOKEN, "๊ณ„์ • ์ •๋ณด๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
}
}

// 4. ์ƒˆ๋กœ์šด ํšŒ์› ์ƒ์„ฑ
// ์ฒซ ๋กœ๊ทธ์ธ ์‹œ email์ด ์—†์œผ๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ
if (email == null || email.isEmpty()) {
throw new BusinessException(ErrorCode.INVALID_TOKEN,
socialType + " ์ฒซ ๋กœ๊ทธ์ธ ์‹œ ์ด๋ฉ”์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.");
}

Member newMember = Member.builder()
.email(email)
.socialId(socialId)
.socialType(socialType)
.status(Status.ACTIVE)
.role(Role.USER)
.build();
return memberRepository.save(newMember);
}
@Override
@CacheEvict(cacheNames = com.divary.global.config.CacheConfig.CACHE_MEMBER_BY_ID, key = "#userId")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtResolver jwtResolver;
private final TokenBlackListService tokenBlackListService;
private final MemberService memberService;
private static final String REACTIVATE_MEMBER_URI = "/api/v1/auth/reactivate";
private static final String REACTIVATE_MEMBER_METHOD = "POST"; //todo ํ•˜๋“œ์ฝ”๋”ฉ ์•ˆํ•˜๊ฒŒ ๋ณ€๊ฒฝ

@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
Expand All @@ -58,12 +56,8 @@ protected void doFilterInternal(@NonNull HttpServletRequest request,

Member member = memberService.findById(userId);

// 1. ํ˜„์žฌ ์š”์ฒญ์ด ํšŒ์› ๋ณต๊ตฌ API์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
boolean isRecoveryRequest = request.getRequestURI().equals(REACTIVATE_MEMBER_URI) &&
request.getMethod().equalsIgnoreCase(REACTIVATE_MEMBER_METHOD);

// 2. ๋ณต๊ตฌ ์š”์ฒญ์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค.
if (!isRecoveryRequest && member.getStatus() == Status.DEACTIVATED) {
// ํƒˆํ‡ด ์‹ ์ฒญ๋œ ๊ณ„์ •์€ API ์ ‘๊ทผ ์ฐจ๋‹จ
if (member.getStatus() == Status.DEACTIVATED) {
throw new BusinessException(ErrorCode.MEMBER_IS_DEACTIVATE);
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/divary/global/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ public enum ErrorCode {
DEVICE_ID_NOT_FOUND(HttpStatus.NOT_FOUND, "DEVICE_001", "๋””๋ฐ”์ด์Šค ์•„์ด๋””๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค"),
MEMBER_IS_DEACTIVATE(HttpStatus.FORBIDDEN, "MEMBER_004", "ํƒˆํ‡ด ์˜ˆ์ •์ธ ๊ณ„์ •์ž…๋‹ˆ๋‹ค."),
CONCURRENT_REQUEST_ERROR(HttpStatus.CONFLICT, "MEMBER_005", "ํƒˆํ‡ด ์š”์ฒญ ์ฒ˜๋ฆฌ ์ค‘ ๋ฐ์ดํ„ฐ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค"),
MEMBER_NOT_DEACTIVATED(HttpStatus.BAD_REQUEST, "MEMBER_006", "ํƒˆํ‡ด ์‹ ์ฒญ๋˜์ง€ ์•Š์€ ๊ณ„์ •์ž…๋‹ˆ๋‹ค."),
//์†Œ์…œ ๋กœ๊ทธ์ธ ๊ด€๋ จ
GOOGLE_BAD_GATEWAY(HttpStatus.BAD_GATEWAY, "GOOGLE_001", "๊ตฌ๊ธ€ ์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค"),
ALREADY_REGISTERED_WITH_DIFFERENT_SOCIAL(HttpStatus.CONFLICT, "AUTH_007", "์ด๋ฏธ ๋‹ค๋ฅธ ์†Œ์…œ ๊ณ„์ •์œผ๋กœ ๊ฐ€์ž…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."),

//์•Œ๋ฆผ ๊ด€๋ จ
NOTIFICAITION_NOT_FOUND(HttpStatus.NOT_FOUND, "MEMBER_003", "ํ•ด๋‹น ID๋ฅผ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž์˜ ์•Œ๋ฆผ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,16 @@ public ApiResponse<DeactivateResponse> deactivateUser(@AuthenticationPrincipal C
return ApiResponse.success(response);
}

@PostMapping(value = "/reactivate")
@Operation(summary = "ํšŒ์› ํƒˆํ‡ด๋ฅผ ์ทจ์†Œํ•ฉ๋‹ˆ๋‹ค.")
@PostMapping(value = "/{socialLoginType}/reactivate")
@Operation(summary = "์†Œ์…œ ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ํšŒ์› ํƒˆํ‡ด๋ฅผ ์ทจ์†Œํ•ฉ๋‹ˆ๋‹ค.")
@ApiSuccessResponse(dataType = void.class)
@ApiErrorExamples(value = {ErrorCode.MEMBER_NOT_FOUND})
public ApiResponse reactivate(@AuthenticationPrincipal CustomUserPrincipal userPrincipal) {
Long userId = userPrincipal.getId();
@ApiErrorExamples(value = {ErrorCode.EMAIL_NOT_FOUND, ErrorCode.MEMBER_NOT_DEACTIVATED})
public ApiResponse reactivate(@PathVariable(name = "socialLoginType") SocialType socialLoginType,
@Valid @RequestBody com.divary.global.oauth.dto.request.RecoveryRequestDto recoveryRequestDto) {
String accessToken = recoveryRequestDto.getAccessToken();
log.info(">> ๋ณต๊ตฌ ์š”์ฒญ - ์†Œ์…œ ํƒ€์ž…: {}, accessToken: {}", socialLoginType, accessToken);

memberService.cancelDeleteMember(userId);
oauthService.reactivate(socialLoginType, accessToken);
return ApiResponse.success("ํšŒ์› ์ •๋ณด ๋ณต๊ตฌ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.divary.global.oauth.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class RecoveryRequestDto {
@NotBlank(message = "access ํ† ํฐ์€ ํ•„์ˆ˜ ์ž…๋ ฅ ๊ฐ’์ž…๋‹ˆ๋‹ค.")
private String accessToken;
}
10 changes: 8 additions & 2 deletions src/main/java/com/divary/global/oauth/infra/AppleJwtParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class AppleJwtParser {
/**
* Apple Identity Token์„ ๊ฒ€์ฆํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
* @param identityToken ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ Identity Token
* @return ์‚ฌ์šฉ์ž ์ •๋ณด (sub: Apple User ID, email: ์ด๋ฉ”์ผ)
* @return ์‚ฌ์šฉ์ž ์ •๋ณด (sub: Apple User ID, email: ์ด๋ฉ”์ผ ๋˜๋Š” ๋นˆ ๋ฌธ์ž์—ด)
*/
public Map<String, String> parse(String identityToken) {
// 1. Apple ๊ณต๊ฐœํ‚ค ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. (์‹ค์ œ ์šด์˜์—์„œ๋Š” ์บ์‹ฑ ํ•„์š”)
Expand Down Expand Up @@ -65,7 +65,13 @@ public Map<String, String> parse(String identityToken) {
// 5. ์ƒ์„ฑ๋œ PublicKey๋กœ ํ† ํฐ์˜ ์„œ๋ช…, ๋ฐœ๊ธ‰์ž, ๋งŒ๋ฃŒ์‹œ๊ฐ„ ๋“ฑ์„ ์ตœ์ข… ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
Claims claims = getClaims(identityToken, publicKey);

return Map.of("sub", claims.getSubject(), "email", claims.get("email", String.class));
String sub = claims.getSubject();
String email = claims.get("email", String.class);

return Map.of(
"sub", sub,
"email", email != null ? email : ""
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ public void logout(SocialType socialLoginType, String deviceId, Long userId) {
socialOauth.logout(deviceId, userId);
}

@Transactional
public void reactivate(SocialType socialLoginType, String accessToken) {
SocialOauth socialOauth = this.findSocialOauthByType(socialLoginType);
if (socialOauth == null) {
throw new BusinessException(ErrorCode.SOCIAL_PROVIDER_NOT_FOUND);
}
socialOauth.reactivate(accessToken);
}

/**
* ์šฐ๋ฆฌ ์„œ๋น„์Šค์˜ Refresh Token์„ ์‚ฌ์šฉํ•˜์—ฌ Access Token๊ณผ Refresh Token์„ ์žฌ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. (RTR)
* ์ด ๋กœ์ง์€ ๋ชจ๋“  ์†Œ์…œ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ณตํ†ต์œผ๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.divary.global.config.jwt.JwtTokenProvider;
import com.divary.global.config.security.CustomUserPrincipal;
import com.divary.global.exception.BusinessException;
import com.divary.global.exception.ErrorCode;
import com.divary.global.oauth.dto.response.LoginResponseDTO;
import com.divary.global.oauth.infra.AppleJwtParser;
import com.divary.global.redis.service.TokenBlackListService;
Expand Down Expand Up @@ -46,9 +47,19 @@ public class AppleOauth implements SocialOauth {
public LoginResponseDTO verifyAndLogin(String identityToken, String deviceId) {
// Identity Token์„ ๊ฒ€์ฆํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
Map<String, String> userInfo = appleJwtParser.parse(identityToken);

String sub = userInfo.get("sub");
String email = userInfo.get("email");

Member member = memberService.findOrCreateMember(email);
log.debug("Apple ๋กœ๊ทธ์ธ - sub: {}, email: {}", sub, email);

// socialId(sub)์™€ socialType์œผ๋กœ ํšŒ์› ์กฐํšŒ ๋˜๋Š” ์ƒ์„ฑ
Member member = memberService.findOrCreateMemberBySocialId(sub, SocialType.APPLE, email);

// ํƒˆํ‡ด ์‹ ์ฒญ๋œ ๊ณ„์ •์€ ๋กœ๊ทธ์ธ ์ฐจ๋‹จ
if (member.getStatus() == Status.DEACTIVATED) {
throw new BusinessException(ErrorCode.MEMBER_IS_DEACTIVATE);
}

CustomUserPrincipal principal = new CustomUserPrincipal(member);

Expand Down Expand Up @@ -78,6 +89,28 @@ public void logout(String deviceId, Long userId) {

log.debug("Apple ๊ณ„์ • ๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌ ์™„๋ฃŒ. UserId: {}, DeviceId: {}", userId, deviceId);
}

@Override
@Transactional
public void reactivate(String identityToken) {
// Identity Token์„ ๊ฒ€์ฆํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.
Map<String, String> userInfo = appleJwtParser.parse(identityToken);
String email = userInfo.get("email");

// ์ด๋ฉ”์ผ๋กœ ํšŒ์› ์ฐพ๊ธฐ
Member member = memberService.findMemberByEmail(email);

// ํƒˆํ‡ด ์‹ ์ฒญ๋œ ๊ณ„์ •์ด ์•„๋‹ˆ๋ฉด ๋ณต๊ตฌ ๋ถˆ๊ฐ€
if (member.getStatus() != Status.DEACTIVATED) {
throw new BusinessException(ErrorCode.MEMBER_NOT_DEACTIVATED);
}

// ๋ณต๊ตฌ ์ฒ˜๋ฆฌ
memberService.cancelDeleteMember(member.getId());

log.debug("Apple ๊ณ„์ • ๋ณต๊ตฌ ์™„๋ฃŒ. Email: {}, UserId: {}", email, member.getId());
}

@Override
public SocialType getType() {
return SocialType.APPLE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,18 @@ private Map<String, Object> requestUserInfo(String accessToken) {
public LoginResponseDTO verifyAndLogin(String googleAccessToken, String deviceId) {
// accessToken์œผ๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ
Map<String, Object> userInfo = requestUserInfo(googleAccessToken);
String sub = (String) userInfo.get("id"); // Google์˜ ๊ณ ์œ  ์‚ฌ์šฉ์ž ID
String email = (String) userInfo.get("email");

log.debug("Google ๋กœ๊ทธ์ธ - sub: {}, email: {}", sub, email);

Member member = memberService.findOrCreateMember(email);
// socialId(sub)์™€ socialType์œผ๋กœ ํšŒ์› ์กฐํšŒ ๋˜๋Š” ์ƒ์„ฑ
Member member = memberService.findOrCreateMemberBySocialId(sub, SocialType.GOOGLE, email);

// ํƒˆํ‡ด ์‹ ์ฒญ๋œ ๊ณ„์ •์€ ๋กœ๊ทธ์ธ ์ฐจ๋‹จ
if (member.getStatus() == Status.DEACTIVATED) {
throw new BusinessException(ErrorCode.MEMBER_IS_DEACTIVATE);
}

CustomUserPrincipal principal = new CustomUserPrincipal(member);

Expand Down Expand Up @@ -103,6 +111,28 @@ public void logout(String deviceId, Long userId) {

log.debug("๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌ ์™„๋ฃŒ. AccessToken ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ์ถ”๊ฐ€, RefreshToken ์‚ญ์ œ. UserId: {}, DeviceId: {}", userId, deviceId);
}

@Override
@Transactional
public void reactivate(String googleAccessToken) {
// accessToken์œผ๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด ์š”์ฒญ
Map<String, Object> userInfo = requestUserInfo(googleAccessToken);
String email = (String) userInfo.get("email");

// ์ด๋ฉ”์ผ๋กœ ํšŒ์› ์ฐพ๊ธฐ
Member member = memberService.findMemberByEmail(email);

// ํƒˆํ‡ด ์‹ ์ฒญ๋œ ๊ณ„์ •์ด ์•„๋‹ˆ๋ฉด ๋ณต๊ตฌ ๋ถˆ๊ฐ€
if (member.getStatus() != Status.DEACTIVATED) {
throw new BusinessException(ErrorCode.MEMBER_NOT_DEACTIVATED);
}

// ๋ณต๊ตฌ ์ฒ˜๋ฆฌ
memberService.cancelDeleteMember(member.getId());

log.debug("๊ณ„์ • ๋ณต๊ตฌ ์™„๋ฃŒ. Email: {}, UserId: {}", email, member.getId());
}

@Override
public SocialType getType() {
return SocialType.GOOGLE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
public interface SocialOauth {
LoginResponseDTO verifyAndLogin(String token, String deviceId);
void logout(String deviceId, Long userId);
void reactivate(String token);
SocialType getType();

}