diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/exception/AuthErrorCode.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/exception/AuthErrorCode.java index 50150b86..7cbf7c20 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/exception/AuthErrorCode.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/exception/AuthErrorCode.java @@ -4,11 +4,10 @@ @Getter public enum AuthErrorCode { - ILLEGAL_MEMBER_ID("01100", "로그인에 실패하였습니다."), - ILLEGAL_TOKEN("01101", "로그인에 실패하였습니다."), - FORBIDDEN_ADMIN_ACCESS("01102", "로그인에 실패하였습니다."), - BLOCKING_MEMBER_ACCESS("01103", "로그인에 실패하였습니다."), - EXPIRED_TOKEN("01104", "기간이 만료된 토큰입니다.") + ILLEGAL_MEMBER_ID("03100", "로그인에 실패하였습니다."), + ILLEGAL_TOKEN("03101", "로그인에 실패하였습니다."), + FORBIDDEN_ADMIN_ACCESS("03102", "로그인에 실패하였습니다."), + BLOCKING_MEMBER_ACCESS("03103", "로그인에 실패하였습니다."), ; private final String code; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AdminAuthInterceptor.java b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AdminAuthInterceptor.java index 7a7cb1bb..9f5c8424 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AdminAuthInterceptor.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AdminAuthInterceptor.java @@ -5,11 +5,10 @@ import com.mapbefine.mapbefine.auth.exception.AuthErrorCode; import com.mapbefine.mapbefine.auth.exception.AuthException; import com.mapbefine.mapbefine.auth.infrastructure.AuthorizationExtractor; -import com.mapbefine.mapbefine.auth.infrastructure.TokenProvider; +import com.mapbefine.mapbefine.auth.infrastructure.JwtTokenProvider; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.util.Objects; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; @@ -19,24 +18,24 @@ public class AdminAuthInterceptor implements HandlerInterceptor { private final AuthorizationExtractor authorizationExtractor; private final AuthService authService; - private final TokenProvider tokenProvider; + private final JwtTokenProvider jwtTokenProvider; public AdminAuthInterceptor( AuthorizationExtractor authorizationExtractor, AuthService authService, - TokenProvider tokenProvider + JwtTokenProvider jwtTokenProvider ) { this.authorizationExtractor = authorizationExtractor; this.authService = authService; - this.tokenProvider = tokenProvider; + this.jwtTokenProvider = jwtTokenProvider; } @Override public boolean preHandle( - @NonNull HttpServletRequest request, - @NonNull HttpServletResponse response, - @NonNull Object handler - ) { + HttpServletRequest request, + HttpServletResponse response, + Object handler + ) throws Exception { if (!(handler instanceof HandlerMethod)) { return true; } @@ -54,9 +53,11 @@ private Long extractMemberIdFromToken(HttpServletRequest request) { if (Objects.isNull(authInfo)) { return null; } - tokenProvider.validateAccessToken(authInfo.accessToken()); - - return Long.parseLong(tokenProvider.getPayload(authInfo.accessToken())); + String accessToken = authInfo.accessToken(); + if (jwtTokenProvider.validateToken(accessToken)) { + return Long.parseLong(jwtTokenProvider.getPayload(accessToken)); + } + throw new AuthException.AuthUnauthorizedException(AuthErrorCode.ILLEGAL_TOKEN); } private void validateAdmin(Long memberId) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java index 7ee91245..01c98c73 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java @@ -3,13 +3,15 @@ import com.mapbefine.mapbefine.auth.application.AuthService; import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.auth.dto.AuthInfo; +import com.mapbefine.mapbefine.auth.exception.AuthErrorCode; +import com.mapbefine.mapbefine.auth.exception.AuthException; +import com.mapbefine.mapbefine.auth.exception.AuthException.AuthUnauthorizedException; import com.mapbefine.mapbefine.auth.infrastructure.AuthorizationExtractor; -import com.mapbefine.mapbefine.auth.infrastructure.TokenProvider; +import com.mapbefine.mapbefine.auth.infrastructure.JwtTokenProvider; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.util.Arrays; import java.util.Objects; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; @@ -19,24 +21,24 @@ public class AuthInterceptor implements HandlerInterceptor { private final AuthorizationExtractor authorizationExtractor; private final AuthService authService; - private final TokenProvider tokenProvider; + private final JwtTokenProvider jwtTokenProvider; public AuthInterceptor( AuthorizationExtractor authorizationExtractor, AuthService authService, - TokenProvider tokenProvider + JwtTokenProvider jwtTokenProvider ) { this.authorizationExtractor = authorizationExtractor; this.authService = authService; - this.tokenProvider = tokenProvider; + this.jwtTokenProvider = jwtTokenProvider; } @Override public boolean preHandle( - @NonNull HttpServletRequest request, - @NonNull HttpServletResponse response, - @NonNull Object handler - ) { + HttpServletRequest request, + HttpServletResponse response, + Object handler + ) throws Exception { if (!(handler instanceof HandlerMethod handlerMethod)) { return true; } @@ -47,7 +49,7 @@ public boolean preHandle( Long memberId = extractMemberIdFromToken(request); if (isLoginRequired((HandlerMethod) handler)) { - authService.validateMember(memberId); + validateMember(memberId); } request.setAttribute("memberId", memberId); @@ -55,6 +57,14 @@ public boolean preHandle( return true; } + private void validateMember(Long memberId) { + if (authService.isMember(memberId)) { + return; + } + + throw new AuthUnauthorizedException(AuthErrorCode.ILLEGAL_MEMBER_ID); + } + private boolean isAuthMemberNotRequired(HandlerMethod handlerMethod) { return Arrays.stream(handlerMethod.getMethodParameters()) .noneMatch(parameter -> parameter.getParameterType().equals(AuthMember.class)); @@ -71,9 +81,11 @@ private Long extractMemberIdFromToken(HttpServletRequest request) { if (Objects.isNull(authInfo)) { return null; } - tokenProvider.validateAccessToken(authInfo.accessToken()); - - return Long.parseLong(tokenProvider.getPayload(authInfo.accessToken())); + String accessToken = authInfo.accessToken(); + if (!jwtTokenProvider.validateToken(accessToken)) { + throw new AuthException.AuthUnauthorizedException(AuthErrorCode.ILLEGAL_TOKEN); + } + return Long.parseLong(jwtTokenProvider.getPayload(accessToken)); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 31ebf243..1d64325e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -100,14 +100,22 @@ private static String createNickname(String nickname) { private static String createNicknameSuffix() { return randomUUID() .toString() - .replace("-", "") + .replaceAll("-", "") .substring(0, DEFAULT_NICKNAME_SUFFIX_LENGTH); } public void update( - String nickName + String nickName, + String email, + String imageUrl ) { - memberInfo = memberInfo.createUpdatedMemberInfo(nickName); + memberInfo = MemberInfo.of( + nickName, + email, + imageUrl, + memberInfo.getRole(), + memberInfo.getStatus() + ); } public void addTopic(Topic topic) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index ee36d80a..3cc5dfa4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -16,6 +16,7 @@ import java.util.Objects; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; @Embeddable @NoArgsConstructor(access = PROTECTED) @@ -28,7 +29,7 @@ public class MemberInfo { @Column(nullable = false, length = 20, unique = true) private String nickName; - @Column(nullable = false) + @Column(nullable = false, unique = true) private String email; @Column(nullable = false) @@ -39,6 +40,7 @@ public class MemberInfo { private Role role; @Enumerated(EnumType.STRING) + @ColumnDefault(value = "NORMAL") @Column(nullable = false) private Status status; @@ -108,11 +110,6 @@ private static void validateStatus(Status status) { } } - public MemberInfo createUpdatedMemberInfo(String nickName) { - - return MemberInfo.of(nickName, this.email, this.imageUrl.getImageUrl(), this.role, this.status); - } - public String getImageUrl() { return imageUrl.getImageUrl(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index 05be31d2..7ac82c62 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -14,4 +14,6 @@ public interface MemberRepository extends JpaRepository { List findAllByMemberInfoRole(Role role); + List findAllByMemberInfoRole(Role role); + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/exception/MemberException.java b/backend/src/main/java/com/mapbefine/mapbefine/member/exception/MemberException.java index b582c64c..89a68948 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/exception/MemberException.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/exception/MemberException.java @@ -1,7 +1,6 @@ package com.mapbefine.mapbefine.member.exception; import com.mapbefine.mapbefine.common.exception.BadRequestException; -import com.mapbefine.mapbefine.common.exception.ConflictException; import com.mapbefine.mapbefine.common.exception.ErrorCode; import com.mapbefine.mapbefine.common.exception.ForbiddenException; import com.mapbefine.mapbefine.common.exception.NotFoundException; @@ -26,11 +25,5 @@ public MemberForbiddenException(MemberErrorCode errorCode, Long id) { } } - public static class MemberConflictException extends ConflictException { - public MemberConflictException(MemberErrorCode errorCode, String value) { - super(new ErrorCode<>(errorCode.getCode(), errorCode.getMessage(), value)); - } - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/oauth/application/OauthService.java b/backend/src/main/java/com/mapbefine/mapbefine/oauth/application/OauthService.java index e7edd8b7..50681719 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/oauth/application/OauthService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/oauth/application/OauthService.java @@ -2,28 +2,32 @@ import com.mapbefine.mapbefine.auth.exception.AuthErrorCode; import com.mapbefine.mapbefine.auth.exception.AuthException.AuthUnauthorizedException; +import com.mapbefine.mapbefine.auth.infrastructure.JwtTokenProvider; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; -import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.oauth.domain.AuthCodeRequestUrlProviderComposite; import com.mapbefine.mapbefine.oauth.domain.OauthMember; import com.mapbefine.mapbefine.oauth.domain.OauthMemberClientComposite; import com.mapbefine.mapbefine.oauth.domain.OauthServerType; +import com.mapbefine.mapbefine.oauth.dto.LoginInfoResponse; import org.springframework.stereotype.Service; @Service public class OauthService { - private final MemberRepository memberRepository; - private final AuthCodeRequestUrlProviderComposite authCodeRequestUrlProviderComposite; - private final OauthMemberClientComposite oauthMemberClientComposite; + private MemberRepository memberRepository; + private JwtTokenProvider jwtTokenProvider; + private AuthCodeRequestUrlProviderComposite authCodeRequestUrlProviderComposite; + private OauthMemberClientComposite oauthMemberClientComposite; public OauthService( MemberRepository memberRepository, + JwtTokenProvider jwtTokenProvider, AuthCodeRequestUrlProviderComposite authCodeRequestUrlProviderComposite, OauthMemberClientComposite oauthMemberClientComposite ) { this.memberRepository = memberRepository; + this.jwtTokenProvider = jwtTokenProvider; this.authCodeRequestUrlProviderComposite = authCodeRequestUrlProviderComposite; this.oauthMemberClientComposite = oauthMemberClientComposite; } @@ -32,14 +36,16 @@ public String getAuthCodeRequestUrl(OauthServerType oauthServerType) { return authCodeRequestUrlProviderComposite.provide(oauthServerType); } - public MemberDetailResponse login(OauthServerType oauthServerType, String code) { + public LoginInfoResponse login(OauthServerType oauthServerType, String code) { OauthMember oauthMember = oauthMemberClientComposite.fetch(oauthServerType, code); Member savedMember = memberRepository.findByOauthId(oauthMember.getOauthId()) .orElseGet(() -> register(oauthMember)); validateMemberStatus(savedMember); - return MemberDetailResponse.from(savedMember); + String accessToken = jwtTokenProvider.createToken(String.valueOf(savedMember.getId())); + + return LoginInfoResponse.of(accessToken, savedMember); } private Member register(OauthMember oauthMember) { @@ -51,6 +57,7 @@ private void validateMemberStatus(Member member) { if (member.isNormalStatus()) { return; } + throw new AuthUnauthorizedException(AuthErrorCode.BLOCKING_MEMBER_ACCESS); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java index a407bcdb..d5128022 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -114,9 +114,6 @@ public int countBookmarks() { return bookmarks.size(); } - public Publicity getPublicity() { - return topicStatus.getPublicity(); - } public void removeImage() { this.topicInfo = topicInfo.removeImage(); }