From 0c3b9329746d68f8bb1c2fd07970b2bf738c05d7 Mon Sep 17 00:00:00 2001 From: Dora Choo Date: Wed, 14 Aug 2024 15:50:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20API=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=EC=97=90=20memberId=EC=99=80=20nickname=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 로그인 API 응답에 memberId와 nickname 필드 추가 * refactor: 로그인용 dto 분리 및 공통 dto에 prefix로 auth 추가 * feat: valid 어노테이션 추가 --- backend/http/auth.http | 2 +- .../auth/controller/AuthController.java | 30 ++++++++++--------- .../auth/controller/CookieProducer.java | 8 ++--- .../chongdae/auth/service/AuthService.java | 22 +++++++++----- .../auth/service/JwtTokenProvider.java | 6 ++-- .../auth/service/dto/AuthInfoDto.java | 4 +++ ...ignupMemberDto.java => AuthMemberDto.java} | 4 +-- .../auth/service/dto/AuthTokenDto.java | 4 +++ .../auth/service/dto/LoginResponse.java | 8 +++++ .../auth/service/dto/SignupResponse.java | 4 +-- .../auth/service/dto/SignupResponseDto.java | 10 ------- .../chongdae/auth/service/dto/TokenDto.java | 4 --- .../auth/integration/AuthIntegrationTest.java | 6 ++++ 13 files changed, 64 insertions(+), 48 deletions(-) create mode 100644 backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthInfoDto.java rename backend/src/main/java/com/zzang/chongdae/auth/service/dto/{SignupMemberDto.java => AuthMemberDto.java} (61%) create mode 100644 backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthTokenDto.java create mode 100644 backend/src/main/java/com/zzang/chongdae/auth/service/dto/LoginResponse.java delete mode 100644 backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponseDto.java delete mode 100644 backend/src/main/java/com/zzang/chongdae/auth/service/dto/TokenDto.java diff --git a/backend/http/auth.http b/backend/http/auth.http index 71832cf9..f8b5f805 100644 --- a/backend/http/auth.http +++ b/backend/http/auth.http @@ -11,7 +11,7 @@ POST {{base-url}}/auth/signup Content-Type: application/json { - "ci": "poke12345678" + "ci": "poke1234567" } ### 토큰 재발급 API diff --git a/backend/src/main/java/com/zzang/chongdae/auth/controller/AuthController.java b/backend/src/main/java/com/zzang/chongdae/auth/controller/AuthController.java index 94dc3a84..be01cf89 100644 --- a/backend/src/main/java/com/zzang/chongdae/auth/controller/AuthController.java +++ b/backend/src/main/java/com/zzang/chongdae/auth/controller/AuthController.java @@ -1,11 +1,12 @@ package com.zzang.chongdae.auth.controller; import com.zzang.chongdae.auth.service.AuthService; +import com.zzang.chongdae.auth.service.dto.AuthInfoDto; +import com.zzang.chongdae.auth.service.dto.AuthTokenDto; import com.zzang.chongdae.auth.service.dto.LoginRequest; +import com.zzang.chongdae.auth.service.dto.LoginResponse; import com.zzang.chongdae.auth.service.dto.SignupRequest; import com.zzang.chongdae.auth.service.dto.SignupResponse; -import com.zzang.chongdae.auth.service.dto.SignupResponseDto; -import com.zzang.chongdae.auth.service.dto.TokenDto; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -26,19 +27,20 @@ public class AuthController { private final CookieConsumer cookieConsumer; @PostMapping("/auth/login") - public ResponseEntity login( + public ResponseEntity login( @RequestBody @Valid LoginRequest request, HttpServletResponse servletResponse) { - TokenDto tokenDto = authService.login(request); - addTokenToHttpServletResponse(tokenDto, servletResponse); - return ResponseEntity.ok().build(); + AuthInfoDto authInfo = authService.login(request); + addTokenToHttpServletResponse(authInfo.authToken(), servletResponse); + LoginResponse response = new LoginResponse(authInfo.authMember()); + return ResponseEntity.ok(response); } @PostMapping("/auth/signup") public ResponseEntity signup( - @RequestBody SignupRequest request, HttpServletResponse servletResponse) { - SignupResponseDto output = authService.signup(request); - SignupResponse response = new SignupResponse(output); - addTokenToHttpServletResponse(output.token(), servletResponse); + @RequestBody @Valid SignupRequest request, HttpServletResponse servletResponse) { + AuthInfoDto authInfo = authService.signup(request); + addTokenToHttpServletResponse(authInfo.authToken(), servletResponse); + SignupResponse response = new SignupResponse(authInfo.authMember()); return ResponseEntity.ok(response); } @@ -46,13 +48,13 @@ public ResponseEntity signup( public ResponseEntity refresh( HttpServletRequest servletRequest, HttpServletResponse servletResponse) { String refreshToken = cookieConsumer.getRefreshToken(servletRequest.getCookies()); - TokenDto tokenDto = authService.refresh(refreshToken); - addTokenToHttpServletResponse(tokenDto, servletResponse); + AuthTokenDto authToken = authService.refresh(refreshToken); + addTokenToHttpServletResponse(authToken, servletResponse); return ResponseEntity.ok().build(); } - private void addTokenToHttpServletResponse(TokenDto tokenDto, HttpServletResponse servletResponse) { - List cookies = cookieExtractor.extractAuthCookies(tokenDto); + private void addTokenToHttpServletResponse(AuthTokenDto authToken, HttpServletResponse servletResponse) { + List cookies = cookieExtractor.extractAuthCookies(authToken); cookieConsumer.addCookies(servletResponse, cookies); } } diff --git a/backend/src/main/java/com/zzang/chongdae/auth/controller/CookieProducer.java b/backend/src/main/java/com/zzang/chongdae/auth/controller/CookieProducer.java index 0b951776..71efe791 100644 --- a/backend/src/main/java/com/zzang/chongdae/auth/controller/CookieProducer.java +++ b/backend/src/main/java/com/zzang/chongdae/auth/controller/CookieProducer.java @@ -1,6 +1,6 @@ package com.zzang.chongdae.auth.controller; -import com.zzang.chongdae.auth.service.dto.TokenDto; +import com.zzang.chongdae.auth.service.dto.AuthTokenDto; import jakarta.servlet.http.Cookie; import java.util.ArrayList; import java.util.List; @@ -12,10 +12,10 @@ public class CookieProducer { private static final String ACCESS_TOKEN_COOKIE_NAME = "access_token"; private static final String REFRESH_TOKEN_COOKIE_NAME = "refresh_token"; - public List extractAuthCookies(TokenDto tokenDto) { + public List extractAuthCookies(AuthTokenDto authToken) { List cookies = new ArrayList<>(); - cookies.add(createCookie(ACCESS_TOKEN_COOKIE_NAME, tokenDto.accessToken())); - cookies.add(createCookie(REFRESH_TOKEN_COOKIE_NAME, tokenDto.refreshToken())); + cookies.add(createCookie(ACCESS_TOKEN_COOKIE_NAME, authToken.accessToken())); + cookies.add(createCookie(REFRESH_TOKEN_COOKIE_NAME, authToken.refreshToken())); return cookies; } diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/AuthService.java b/backend/src/main/java/com/zzang/chongdae/auth/service/AuthService.java index 55c9994b..ad717ad7 100644 --- a/backend/src/main/java/com/zzang/chongdae/auth/service/AuthService.java +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/AuthService.java @@ -1,10 +1,11 @@ package com.zzang.chongdae.auth.service; import com.zzang.chongdae.auth.exception.AuthErrorCode; +import com.zzang.chongdae.auth.service.dto.AuthInfoDto; +import com.zzang.chongdae.auth.service.dto.AuthMemberDto; +import com.zzang.chongdae.auth.service.dto.AuthTokenDto; import com.zzang.chongdae.auth.service.dto.LoginRequest; import com.zzang.chongdae.auth.service.dto.SignupRequest; -import com.zzang.chongdae.auth.service.dto.SignupResponseDto; -import com.zzang.chongdae.auth.service.dto.TokenDto; import com.zzang.chongdae.global.exception.MarketException; import com.zzang.chongdae.member.exception.MemberErrorCode; import com.zzang.chongdae.member.repository.MemberRepository; @@ -23,26 +24,31 @@ public class AuthService { private final JwtTokenProvider jwtTokenProvider; private final NicknameGenerator nickNameGenerator; - public TokenDto login(LoginRequest request) { + public AuthInfoDto login(LoginRequest request) { String password = passwordEncoder.encode(request.ci()); MemberEntity member = memberRepository.findByPassword(password) .orElseThrow(() -> new MarketException(AuthErrorCode.INVALID_PASSWORD)); - return jwtTokenProvider.createAuthToken(member.getId().toString()); + return createTokenByMember(member); } @Transactional - public SignupResponseDto signup(SignupRequest request) { + public AuthInfoDto signup(SignupRequest request) { String password = passwordEncoder.encode(request.ci()); if (memberRepository.existsByPassword(password)) { throw new MarketException(AuthErrorCode.DUPLICATED_MEMBER); } MemberEntity member = new MemberEntity(nickNameGenerator.generate(), password); MemberEntity savedMember = memberRepository.save(member); - TokenDto tokenDto = jwtTokenProvider.createAuthToken(savedMember.getId().toString()); - return new SignupResponseDto(savedMember, tokenDto); + return createTokenByMember(savedMember); } - public TokenDto refresh(String refreshToken) { + private AuthInfoDto createTokenByMember(MemberEntity member) { + AuthMemberDto authMember = new AuthMemberDto(member); + AuthTokenDto authToken = jwtTokenProvider.createAuthToken(member.getId().toString()); + return new AuthInfoDto(authMember, authToken); + } + + public AuthTokenDto refresh(String refreshToken) { Long memberId = jwtTokenProvider.getMemberIdByRefreshToken(refreshToken); return jwtTokenProvider.createAuthToken(memberId.toString()); } diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/JwtTokenProvider.java b/backend/src/main/java/com/zzang/chongdae/auth/service/JwtTokenProvider.java index 0acc746c..a7cba476 100644 --- a/backend/src/main/java/com/zzang/chongdae/auth/service/JwtTokenProvider.java +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/JwtTokenProvider.java @@ -1,7 +1,7 @@ package com.zzang.chongdae.auth.service; import com.zzang.chongdae.auth.exception.AuthErrorCode; -import com.zzang.chongdae.auth.service.dto.TokenDto; +import com.zzang.chongdae.auth.service.dto.AuthTokenDto; import com.zzang.chongdae.global.exception.MarketException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; @@ -36,8 +36,8 @@ public JwtTokenProvider(@Value("${security.jwt.token.access-secret-key}") String this.clock = clock; } - public TokenDto createAuthToken(String payload) { - return new TokenDto(createToken(payload, accessSecretKey, accessTokenExpired), + public AuthTokenDto createAuthToken(String payload) { + return new AuthTokenDto(createToken(payload, accessSecretKey, accessTokenExpired), createToken(payload, refreshSecretKey, refreshTokenExpired)); } diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthInfoDto.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthInfoDto.java new file mode 100644 index 00000000..aa733d0f --- /dev/null +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthInfoDto.java @@ -0,0 +1,4 @@ +package com.zzang.chongdae.auth.service.dto; + +public record AuthInfoDto(AuthMemberDto authMember, AuthTokenDto authToken) { +} diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupMemberDto.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthMemberDto.java similarity index 61% rename from backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupMemberDto.java rename to backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthMemberDto.java index c79af3fa..894bfff4 100644 --- a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupMemberDto.java +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthMemberDto.java @@ -2,9 +2,9 @@ import com.zzang.chongdae.member.repository.entity.MemberEntity; -public record SignupMemberDto(Long id, String nickname) { +public record AuthMemberDto(Long id, String nickname) { - public SignupMemberDto(MemberEntity member) { + public AuthMemberDto(MemberEntity member) { this(member.getId(), member.getNickname()); } } diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthTokenDto.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthTokenDto.java new file mode 100644 index 00000000..a28b7bf2 --- /dev/null +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/AuthTokenDto.java @@ -0,0 +1,4 @@ +package com.zzang.chongdae.auth.service.dto; + +public record AuthTokenDto(String accessToken, String refreshToken) { +} diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/LoginResponse.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/LoginResponse.java new file mode 100644 index 00000000..c2fdcab2 --- /dev/null +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/LoginResponse.java @@ -0,0 +1,8 @@ +package com.zzang.chongdae.auth.service.dto; + +public record LoginResponse(Long memberId, String nickname) { + + public LoginResponse(AuthMemberDto authMember) { + this(authMember.id(), authMember.nickname()); + } +} diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponse.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponse.java index 2025c034..9911ff56 100644 --- a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponse.java +++ b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponse.java @@ -2,7 +2,7 @@ public record SignupResponse(Long memberId, String nickname) { - public SignupResponse(SignupResponseDto output) { - this(output.member().id(), output.member().nickname()); + public SignupResponse(AuthMemberDto authMember) { + this(authMember.id(), authMember.nickname()); } } diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponseDto.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponseDto.java deleted file mode 100644 index 3c4f20a0..00000000 --- a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/SignupResponseDto.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.zzang.chongdae.auth.service.dto; - -import com.zzang.chongdae.member.repository.entity.MemberEntity; - -public record SignupResponseDto(SignupMemberDto member, TokenDto token) { - - public SignupResponseDto(MemberEntity member, TokenDto token) { - this(new SignupMemberDto(member), token); - } -} diff --git a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/TokenDto.java b/backend/src/main/java/com/zzang/chongdae/auth/service/dto/TokenDto.java deleted file mode 100644 index 6018ce11..00000000 --- a/backend/src/main/java/com/zzang/chongdae/auth/service/dto/TokenDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.zzang.chongdae.auth.service.dto; - -public record TokenDto(String accessToken, String refreshToken) { -} diff --git a/backend/src/test/java/com/zzang/chongdae/auth/integration/AuthIntegrationTest.java b/backend/src/test/java/com/zzang/chongdae/auth/integration/AuthIntegrationTest.java index 763b8939..5391e11d 100644 --- a/backend/src/test/java/com/zzang/chongdae/auth/integration/AuthIntegrationTest.java +++ b/backend/src/test/java/com/zzang/chongdae/auth/integration/AuthIntegrationTest.java @@ -36,6 +36,10 @@ class Login { List requestDescriptors = List.of( fieldWithPath("ci").description("회원 식별자 인증 정보") ); + List responseDescriptors = List.of( + fieldWithPath("memberId").description("회원 id"), + fieldWithPath("nickname").description("닉네임") + ); List responseHeaderDescriptors = List.of( headerWithName("Set-Cookie").description(""" access_token=a.b.c; Path=/; HttpOnly \n @@ -46,8 +50,10 @@ class Login { .summary("회원 로그인") .description("회원 식별자 인증 정보로 로그인 합니다.") .requestFields(requestDescriptors) + .responseFields(responseDescriptors) .responseHeaders(responseHeaderDescriptors) .requestSchema(schema("LonginRequest")) + .responseSchema(schema("LoginResponse")) .build(); MemberEntity member;