From db45fad48c209d1c741550d0854b8b3e1524111c Mon Sep 17 00:00:00 2001 From: dwl21 Date: Fri, 11 Apr 2025 13:03:48 +0900 Subject: [PATCH 01/43] =?UTF-8?q?fix:=20=EC=9D=98=EC=A1=B4=EC=84=B1=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index a0aabaf..7025e84 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,6 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test:3.4.4' testImplementation 'io.rest-assured:rest-assured:5.5.1' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.12.1' } tasks.named('test') { From d5566d2c2a1a15ae18a20a91215f06c68118655a Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Tue, 15 Apr 2025 21:05:40 +0900 Subject: [PATCH 02/43] =?UTF-8?q?feat:=201=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/auth/AuthController.java | 54 +++++++++++++++++++ .../yourssu/roomescape/auth/AuthService.java | 29 ++++++++++ .../roomescape/auth/CheckLoginResponse.java | 14 +++++ .../yourssu/roomescape/auth/LoginRequest.java | 19 +++++++ .../roomescape/exception/CustomException.java | 15 ++++++ .../roomescape/exception/ErrorCode.java | 25 +++++++++ .../roomescape/exception/ErrorResponse.java | 20 +++++++ .../exception/GlobalExceptionHandler.java | 16 ++++++ .../yourssu/roomescape/jwt/TokenProvider.java | 39 ++++++++++++++ .../yourssu/roomescape/member/MemberDao.java | 53 ++++++++++-------- src/main/resources/application.properties | 3 +- .../yourssu/roomescape/MissionStepTest.java | 10 ++++ 12 files changed, 275 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/yourssu/roomescape/auth/AuthController.java create mode 100644 src/main/java/com/yourssu/roomescape/auth/AuthService.java create mode 100644 src/main/java/com/yourssu/roomescape/auth/CheckLoginResponse.java create mode 100644 src/main/java/com/yourssu/roomescape/auth/LoginRequest.java create mode 100644 src/main/java/com/yourssu/roomescape/exception/CustomException.java create mode 100644 src/main/java/com/yourssu/roomescape/exception/ErrorCode.java create mode 100644 src/main/java/com/yourssu/roomescape/exception/ErrorResponse.java create mode 100644 src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/com/yourssu/roomescape/jwt/TokenProvider.java diff --git a/src/main/java/com/yourssu/roomescape/auth/AuthController.java b/src/main/java/com/yourssu/roomescape/auth/AuthController.java new file mode 100644 index 0000000..34e868c --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/AuthController.java @@ -0,0 +1,54 @@ +package com.yourssu.roomescape.auth; + +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; + +@RestController +public class AuthController { + + private final AuthService authService; + + public AuthController(AuthService authService) { + this.authService = authService; + } + + @PostMapping("/login") + public ResponseEntity login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) { + + String accessToken = authService.login(loginRequest); + Cookie cookie = new Cookie("token", accessToken); + cookie.setHttpOnly(true); + cookie.setPath("/"); + cookie.setMaxAge(0); + response.addCookie(cookie); + return ResponseEntity.ok().build(); + } + + @GetMapping("/login/check") + public ResponseEntity loginCheck(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + String token = null; + + if (cookies != null) { + token = Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .map(Cookie::getValue) + .findFirst() + .orElseThrow(() -> new CustomException(ErrorCode.TOKEN_NOT_FOUND)); + } + + CheckLoginResponse checkLoginResponse = authService.checkLogin(token); + + return ResponseEntity.ok().body(checkLoginResponse); + } +} diff --git a/src/main/java/com/yourssu/roomescape/auth/AuthService.java b/src/main/java/com/yourssu/roomescape/auth/AuthService.java new file mode 100644 index 0000000..d7f41cb --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/AuthService.java @@ -0,0 +1,29 @@ +package com.yourssu.roomescape.auth; + +import com.yourssu.roomescape.jwt.TokenProvider; +import com.yourssu.roomescape.member.Member; +import com.yourssu.roomescape.member.MemberDao; +import org.springframework.stereotype.Service; + +@Service +public class AuthService { + + private final MemberDao memberDao; + private final TokenProvider tokenProvider; + + public AuthService(TokenProvider tokenProvider, MemberDao memberDao) { + this.tokenProvider = tokenProvider; + this.memberDao = memberDao; + } + + public String login(LoginRequest loginRequest) { + Member member = memberDao.findByEmailAndPassword(loginRequest.getEmail(), loginRequest.getPassword()); + return tokenProvider.createToken(member.getEmail()); + } + + public CheckLoginResponse checkLogin(String token) { + String payload = tokenProvider.getPayload(token); + Member member = memberDao.findByEmail(payload); + return new CheckLoginResponse(member.getName()); + } +} diff --git a/src/main/java/com/yourssu/roomescape/auth/CheckLoginResponse.java b/src/main/java/com/yourssu/roomescape/auth/CheckLoginResponse.java new file mode 100644 index 0000000..caebc75 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/CheckLoginResponse.java @@ -0,0 +1,14 @@ +package com.yourssu.roomescape.auth; + +public class CheckLoginResponse { + + private String name; + + public CheckLoginResponse(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/com/yourssu/roomescape/auth/LoginRequest.java b/src/main/java/com/yourssu/roomescape/auth/LoginRequest.java new file mode 100644 index 0000000..3e10689 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/LoginRequest.java @@ -0,0 +1,19 @@ +package com.yourssu.roomescape.auth; + +public class LoginRequest { + private String email; + private String password; + + public LoginRequest(String email, String password) { + this.email = email; + this.password = password; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } +} diff --git a/src/main/java/com/yourssu/roomescape/exception/CustomException.java b/src/main/java/com/yourssu/roomescape/exception/CustomException.java new file mode 100644 index 0000000..c6dc596 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/exception/CustomException.java @@ -0,0 +1,15 @@ +package com.yourssu.roomescape.exception; + +public class CustomException extends RuntimeException { + + private final ErrorCode errorCode; + + public ErrorCode getErrorCode() { + return errorCode; + } + + public CustomException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } +} diff --git a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java new file mode 100644 index 0000000..2c893c3 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java @@ -0,0 +1,25 @@ +package com.yourssu.roomescape.exception; + +import org.springframework.http.HttpStatus; + +public enum ErrorCode { + + TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키에 토큰이 존재하지 않습니다."), + MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자의 정보를 찾을 수 없습니다."); + + private final HttpStatus status; + private final String message; + + ErrorCode(HttpStatus status, String message) { + this.status = status; + this.message = message; + } + + public HttpStatus getStatus() { + return status; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/yourssu/roomescape/exception/ErrorResponse.java b/src/main/java/com/yourssu/roomescape/exception/ErrorResponse.java new file mode 100644 index 0000000..5053ea0 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/exception/ErrorResponse.java @@ -0,0 +1,20 @@ +package com.yourssu.roomescape.exception; + +public class ErrorResponse { + + private final String code; + private final String message; + + public ErrorResponse(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java b/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..b9b2f99 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java @@ -0,0 +1,16 @@ +package com.yourssu.roomescape.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(CustomException.class) + public ResponseEntity handleCustomException(CustomException e) { + ErrorCode errorCode = e.getErrorCode(); + ErrorResponse response = new ErrorResponse(errorCode.name(), errorCode.getMessage()); + return ResponseEntity.status(errorCode.getStatus()).body(response); + } +} diff --git a/src/main/java/com/yourssu/roomescape/jwt/TokenProvider.java b/src/main/java/com/yourssu/roomescape/jwt/TokenProvider.java new file mode 100644 index 0000000..2056c51 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/jwt/TokenProvider.java @@ -0,0 +1,39 @@ +package com.yourssu.roomescape.jwt; + +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class TokenProvider { + @Value("${security.jwt.token.secret-key}") + private String secretKey; + @Value("${security.jwt.token.expire-length}") + private long validityInMilliseconds; + + public String createToken(String payload) { + Claims claims = Jwts.claims().subject(payload).build(); + Date now = new Date(); + Date validity = new Date(now.getTime() + validityInMilliseconds); + + + return Jwts.builder() + .claims(claims) + .issuedAt(now) + .expiration(validity) + .signWith(Keys.hmacShaKeyFor(secretKey.getBytes())) + .compact(); + } + + public String getPayload(String token) { + return Jwts.parser() + .verifyWith(Keys.hmacShaKeyFor(secretKey.getBytes())) + .build() + .parseSignedClaims(token) + .getPayload() + .getSubject(); + } +} diff --git a/src/main/java/com/yourssu/roomescape/member/MemberDao.java b/src/main/java/com/yourssu/roomescape/member/MemberDao.java index 7923c15..2d793ce 100644 --- a/src/main/java/com/yourssu/roomescape/member/MemberDao.java +++ b/src/main/java/com/yourssu/roomescape/member/MemberDao.java @@ -1,5 +1,8 @@ package com.yourssu.roomescape.member; +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; @@ -28,28 +31,36 @@ public Member save(Member member) { } public Member findByEmailAndPassword(String email, String password) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - email, password - ); + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", + (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("role") + ), + email, password + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } } - public Member findByName(String name) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - name - ); + public Member findByEmail(String email) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE email = ?", + (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("role") + ), + email + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a0f33bb..eccb1f3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,4 +8,5 @@ spring.datasource.url=jdbc:h2:mem:database #spring.jpa.ddl-auto=create-drop #spring.jpa.defer-datasource-initialization=true -#roomescape.auth.jwt.secret= Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E= \ No newline at end of file +security.jwt.token.secret-key=Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E= +security.jwt.token.expire-length=3600000 \ No newline at end of file diff --git a/src/test/java/com/yourssu/roomescape/MissionStepTest.java b/src/test/java/com/yourssu/roomescape/MissionStepTest.java index 085d0d6..9025b76 100644 --- a/src/test/java/com/yourssu/roomescape/MissionStepTest.java +++ b/src/test/java/com/yourssu/roomescape/MissionStepTest.java @@ -34,5 +34,15 @@ public class MissionStepTest { String token = response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; assertThat(token).isNotBlank(); + + ExtractableResponse checkResponse = RestAssured.given().log().all() + .contentType(ContentType.JSON) + .cookie("token", token) + .when().get("/login/check") + .then().log().all() + .statusCode(200) + .extract(); + + assertThat(checkResponse.body().jsonPath().getString("name")).isEqualTo("어드민"); } } From cdffb4fc82b91154172ff7d31ecaffd303c7a23f Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Wed, 16 Apr 2025 17:39:26 +0900 Subject: [PATCH 03/43] =?UTF-8?q?feat:=202=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A6=AC=ED=8C=A9=ED=84=B0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/auth/AuthController.java | 5 +- .../yourssu/roomescape/auth/AuthService.java | 5 +- .../yourssu/roomescape/auth/LoginMember.java | 11 +++++ .../auth/LoginMemberArgumentResolver.java | 47 +++++++++++++++++++ .../yourssu/roomescape/config/WebConfig.java | 23 +++++++++ .../roomescape/exception/ErrorCode.java | 3 +- .../yourssu/roomescape/member/MemberDao.java | 17 +++++++ .../reservation/ReservationController.java | 12 ++--- .../reservation/ReservationRequest.java | 8 ++++ .../reservation/ReservationService.java | 42 ++++++++++++++--- .../yourssu/roomescape/MissionStepTest.java | 42 +++++++++++++++++ 11 files changed, 194 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/yourssu/roomescape/auth/LoginMember.java create mode 100644 src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java create mode 100644 src/main/java/com/yourssu/roomescape/config/WebConfig.java diff --git a/src/main/java/com/yourssu/roomescape/auth/AuthController.java b/src/main/java/com/yourssu/roomescape/auth/AuthController.java index 34e868c..df0945c 100644 --- a/src/main/java/com/yourssu/roomescape/auth/AuthController.java +++ b/src/main/java/com/yourssu/roomescape/auth/AuthController.java @@ -47,8 +47,7 @@ public ResponseEntity loginCheck(HttpServletRequest request) .orElseThrow(() -> new CustomException(ErrorCode.TOKEN_NOT_FOUND)); } - CheckLoginResponse checkLoginResponse = authService.checkLogin(token); - - return ResponseEntity.ok().body(checkLoginResponse); + String name = authService.checkLogin(token).getName(); + return ResponseEntity.ok().body(new CheckLoginResponse(name)); } } diff --git a/src/main/java/com/yourssu/roomescape/auth/AuthService.java b/src/main/java/com/yourssu/roomescape/auth/AuthService.java index d7f41cb..acabe75 100644 --- a/src/main/java/com/yourssu/roomescape/auth/AuthService.java +++ b/src/main/java/com/yourssu/roomescape/auth/AuthService.java @@ -21,9 +21,8 @@ public String login(LoginRequest loginRequest) { return tokenProvider.createToken(member.getEmail()); } - public CheckLoginResponse checkLogin(String token) { + public Member checkLogin(String token) { String payload = tokenProvider.getPayload(token); - Member member = memberDao.findByEmail(payload); - return new CheckLoginResponse(member.getName()); + return memberDao.findByEmail(payload); } } diff --git a/src/main/java/com/yourssu/roomescape/auth/LoginMember.java b/src/main/java/com/yourssu/roomescape/auth/LoginMember.java new file mode 100644 index 0000000..6bd03f9 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/LoginMember.java @@ -0,0 +1,11 @@ +package com.yourssu.roomescape.auth; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginMember { +} diff --git a/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java b/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java new file mode 100644 index 0000000..3f50415 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java @@ -0,0 +1,47 @@ +package com.yourssu.roomescape.auth; + +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import java.util.Arrays; + +@Component +public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + + private final AuthService authService; + + public LoginMemberArgumentResolver(AuthService authService) { + this.authService = authService; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(LoginMember.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + + Cookie[] cookies = request.getCookies(); + String token = null; + + if (cookies != null) { + token = Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .map(Cookie::getValue) + .findFirst() + .orElseThrow(() -> new CustomException(ErrorCode.TOKEN_NOT_FOUND)); + } + + return authService.checkLogin(token); + } +} diff --git a/src/main/java/com/yourssu/roomescape/config/WebConfig.java b/src/main/java/com/yourssu/roomescape/config/WebConfig.java new file mode 100644 index 0000000..da0f889 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/config/WebConfig.java @@ -0,0 +1,23 @@ +package com.yourssu.roomescape.config; + +import com.yourssu.roomescape.auth.LoginMemberArgumentResolver; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + private final LoginMemberArgumentResolver loginMemberArgumentResolver; + + public WebConfig(LoginMemberArgumentResolver loginMemberArgumentResolver) { + this.loginMemberArgumentResolver = loginMemberArgumentResolver; + } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(loginMemberArgumentResolver); + } +} diff --git a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java index 2c893c3..319cdf7 100644 --- a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java +++ b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java @@ -5,7 +5,8 @@ public enum ErrorCode { TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키에 토큰이 존재하지 않습니다."), - MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자의 정보를 찾을 수 없습니다."); + MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자의 정보를 찾을 수 없습니다."), + INVALID_RESERVATION_REQUEST(HttpStatus.BAD_REQUEST, "예약 요청 값이 누락되었습니다."); private final HttpStatus status; private final String message; diff --git a/src/main/java/com/yourssu/roomescape/member/MemberDao.java b/src/main/java/com/yourssu/roomescape/member/MemberDao.java index 2d793ce..3a1166d 100644 --- a/src/main/java/com/yourssu/roomescape/member/MemberDao.java +++ b/src/main/java/com/yourssu/roomescape/member/MemberDao.java @@ -63,4 +63,21 @@ public Member findByEmail(String email) { throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); } } + + public Member findByName(String name) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE name = ?", + (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("role") + ), + name + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } + } } diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java index 77f108d..80f9854 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java @@ -1,5 +1,7 @@ package com.yourssu.roomescape.reservation; +import com.yourssu.roomescape.auth.LoginMember; +import com.yourssu.roomescape.member.Member; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -21,14 +23,8 @@ public List list() { } @PostMapping("/reservations") - public ResponseEntity create(@RequestBody ReservationRequest reservationRequest) { - if (reservationRequest.getName() == null - || reservationRequest.getDate() == null - || reservationRequest.getTheme() == null - || reservationRequest.getTime() == null) { - return ResponseEntity.badRequest().build(); - } - ReservationResponse reservation = reservationService.save(reservationRequest); + public ResponseEntity create(@RequestBody ReservationRequest reservationRequest, @LoginMember Member member) { + ReservationResponse reservation = reservationService.save(reservationRequest, member); return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); } diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationRequest.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationRequest.java index b413312..00f716a 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationRequest.java @@ -2,10 +2,18 @@ public class ReservationRequest { private String name; + private String date; private Long theme; private Long time; + public ReservationRequest(String name, String date, Long theme, Long time) { + this.name = name; + this.date = date; + this.theme = theme; + this.time = time; + } + public String getName() { return name; } diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java index 1dab4f6..328c357 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java @@ -1,21 +1,51 @@ package com.yourssu.roomescape.reservation; +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; +import com.yourssu.roomescape.member.Member; +import com.yourssu.roomescape.member.MemberDao; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Optional; @Service public class ReservationService { - private ReservationDao reservationDao; + private final ReservationDao reservationDao; + private final MemberDao memberDao; - public ReservationService(ReservationDao reservationDao) { + public ReservationService(ReservationDao reservationDao, MemberDao memberDao) { this.reservationDao = reservationDao; + this.memberDao = memberDao; } - public ReservationResponse save(ReservationRequest reservationRequest) { - Reservation reservation = reservationDao.save(reservationRequest); - - return new ReservationResponse(reservation.getId(), reservationRequest.getName(), reservation.getTheme().getName(), reservation.getDate(), reservation.getTime().getValue()); + public ReservationResponse save(ReservationRequest reservationRequest, Member member) { + if (reservationRequest.getDate() == null || reservationRequest.getTheme() == null || reservationRequest.getTime() == null) { + throw new CustomException(ErrorCode.INVALID_RESERVATION_REQUEST); + } + + String memberName = Optional.ofNullable(reservationRequest.getName()) + .map(name -> { + Member existingMember = memberDao.findByName(name); + return existingMember.getName(); + }) + .orElse(member.getName()); + + ReservationRequest updatedRequest = new ReservationRequest( + memberName, + reservationRequest.getDate(), + reservationRequest.getTheme(), + reservationRequest.getTime() + ); + + Reservation reservation = reservationDao.save(updatedRequest); + + return new ReservationResponse( + reservation.getId(), + reservation.getName(), + reservation.getTheme().getName(), + reservation.getDate(), + reservation.getTime().getValue()); } public void deleteById(Long id) { diff --git a/src/test/java/com/yourssu/roomescape/MissionStepTest.java b/src/test/java/com/yourssu/roomescape/MissionStepTest.java index 9025b76..38caa07 100644 --- a/src/test/java/com/yourssu/roomescape/MissionStepTest.java +++ b/src/test/java/com/yourssu/roomescape/MissionStepTest.java @@ -1,10 +1,15 @@ package com.yourssu.roomescape; +import com.yourssu.roomescape.auth.AuthService; +import com.yourssu.roomescape.auth.LoginRequest; +import com.yourssu.roomescape.jwt.TokenProvider; +import com.yourssu.roomescape.reservation.ReservationResponse; import io.restassured.RestAssured; import io.restassured.http.ContentType; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; @@ -17,6 +22,8 @@ @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) public class MissionStepTest { + @Autowired private AuthService authService; + @Test void 일단계() { Map params = new HashMap<>(); @@ -45,4 +52,39 @@ public class MissionStepTest { assertThat(checkResponse.body().jsonPath().getString("name")).isEqualTo("어드민"); } + + @Test + void 이단계() { + LoginRequest loginRequest = new LoginRequest("admin@email.com", "password"); + String token = authService.login(loginRequest); + + Map params = new HashMap<>(); + params.put("date", "2024-03-01"); + params.put("time", "1"); + params.put("theme", "1"); + + ExtractableResponse response = RestAssured.given().log().all() + .body(params) + .cookie("token", token) + .contentType(ContentType.JSON) + .post("/reservations") + .then().log().all() + .extract(); + + assertThat(response.statusCode()).isEqualTo(201); + assertThat(response.as(ReservationResponse.class).getName()).isEqualTo("어드민"); + + params.put("name", "브라운"); + + ExtractableResponse adminResponse = RestAssured.given().log().all() + .body(params) + .cookie("token", token) + .contentType(ContentType.JSON) + .post("/reservations") + .then().log().all() + .extract(); + + assertThat(adminResponse.statusCode()).isEqualTo(201); + assertThat(adminResponse.as(ReservationResponse.class).getName()).isEqualTo("브라운"); + } } From 11b44d1c74768b8674edc004fbfead8ad0210da0 Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Wed, 16 Apr 2025 21:42:21 +0900 Subject: [PATCH 04/43] =?UTF-8?q?feat:=203=EB=8B=A8=EA=B3=84=20-=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/AdminAuthorizationInterceptor.java | 34 +++++++++++++++++++ .../roomescape/auth/AuthController.java | 15 ++------ .../auth/LoginMemberArgumentResolver.java | 15 ++------ .../yourssu/roomescape/config/WebConfig.java | 12 ++++++- .../roomescape/exception/ErrorCode.java | 4 ++- .../roomescape/jwt/TokenExtractor.java | 26 ++++++++++++++ .../yourssu/roomescape/MissionStepTest.java | 22 +++++++++++- 7 files changed, 99 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java create mode 100644 src/main/java/com/yourssu/roomescape/jwt/TokenExtractor.java diff --git a/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java b/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java new file mode 100644 index 0000000..d640dc6 --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java @@ -0,0 +1,34 @@ +package com.yourssu.roomescape.auth; + +import com.yourssu.roomescape.jwt.TokenExtractor; +import com.yourssu.roomescape.member.Member; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class AdminAuthorizationInterceptor implements HandlerInterceptor { + + private final AuthService authService; + + public AdminAuthorizationInterceptor(AuthService authService) { + this.authService = authService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Cookie[] cookies = request.getCookies(); + String token = TokenExtractor.extractTokenFromCookies(cookies); + Member member = authService.checkLogin(token); + + if(!"ADMIN".equals(member.getRole())) { + response.setStatus(401); + response.getWriter().write("해당 접근에 대한 권한이 없습니다."); + return false; + } + + return true; + } +} diff --git a/src/main/java/com/yourssu/roomescape/auth/AuthController.java b/src/main/java/com/yourssu/roomescape/auth/AuthController.java index df0945c..2ff122c 100644 --- a/src/main/java/com/yourssu/roomescape/auth/AuthController.java +++ b/src/main/java/com/yourssu/roomescape/auth/AuthController.java @@ -1,7 +1,6 @@ package com.yourssu.roomescape.auth; -import com.yourssu.roomescape.exception.CustomException; -import com.yourssu.roomescape.exception.ErrorCode; +import com.yourssu.roomescape.jwt.TokenExtractor; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -11,8 +10,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import java.util.Arrays; - @RestController public class AuthController { @@ -37,15 +34,7 @@ public ResponseEntity login(@RequestBody LoginRequest loginRequest, HttpServl @GetMapping("/login/check") public ResponseEntity loginCheck(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); - String token = null; - - if (cookies != null) { - token = Arrays.stream(cookies) - .filter(cookie -> "token".equals(cookie.getName())) - .map(Cookie::getValue) - .findFirst() - .orElseThrow(() -> new CustomException(ErrorCode.TOKEN_NOT_FOUND)); - } + String token = TokenExtractor.extractTokenFromCookies(cookies); String name = authService.checkLogin(token).getName(); return ResponseEntity.ok().body(new CheckLoginResponse(name)); diff --git a/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java b/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java index 3f50415..bfd7718 100644 --- a/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java +++ b/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java @@ -1,7 +1,6 @@ package com.yourssu.roomescape.auth; -import com.yourssu.roomescape.exception.CustomException; -import com.yourssu.roomescape.exception.ErrorCode; +import com.yourssu.roomescape.jwt.TokenExtractor; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; @@ -11,8 +10,6 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; -import java.util.Arrays; - @Component public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { @@ -32,15 +29,7 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); Cookie[] cookies = request.getCookies(); - String token = null; - - if (cookies != null) { - token = Arrays.stream(cookies) - .filter(cookie -> "token".equals(cookie.getName())) - .map(Cookie::getValue) - .findFirst() - .orElseThrow(() -> new CustomException(ErrorCode.TOKEN_NOT_FOUND)); - } + String token = TokenExtractor.extractTokenFromCookies(cookies); return authService.checkLogin(token); } diff --git a/src/main/java/com/yourssu/roomescape/config/WebConfig.java b/src/main/java/com/yourssu/roomescape/config/WebConfig.java index da0f889..eed4104 100644 --- a/src/main/java/com/yourssu/roomescape/config/WebConfig.java +++ b/src/main/java/com/yourssu/roomescape/config/WebConfig.java @@ -1,8 +1,10 @@ package com.yourssu.roomescape.config; +import com.yourssu.roomescape.auth.AdminAuthorizationInterceptor; import com.yourssu.roomescape.auth.LoginMemberArgumentResolver; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @@ -11,13 +13,21 @@ public class WebConfig implements WebMvcConfigurer { private final LoginMemberArgumentResolver loginMemberArgumentResolver; + private final AdminAuthorizationInterceptor adminAuthorizationInterceptor; - public WebConfig(LoginMemberArgumentResolver loginMemberArgumentResolver) { + public WebConfig(LoginMemberArgumentResolver loginMemberArgumentResolver, AdminAuthorizationInterceptor adminAuthorizationInterceptor) { this.loginMemberArgumentResolver = loginMemberArgumentResolver; + this.adminAuthorizationInterceptor = adminAuthorizationInterceptor; } @Override public void addArgumentResolvers(List resolvers) { resolvers.add(loginMemberArgumentResolver); } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(adminAuthorizationInterceptor) + .addPathPatterns("/admin/**"); + } } diff --git a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java index 319cdf7..311b9f7 100644 --- a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java +++ b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java @@ -4,9 +4,11 @@ public enum ErrorCode { + COOKIE_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키가 존재하지 않습니다."), TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키에 토큰이 존재하지 않습니다."), MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자의 정보를 찾을 수 없습니다."), - INVALID_RESERVATION_REQUEST(HttpStatus.BAD_REQUEST, "예약 요청 값이 누락되었습니다."); + INVALID_RESERVATION_REQUEST(HttpStatus.BAD_REQUEST, "예약 요청 값이 누락되었습니다."), + UNAUTHORIZED_ACCESS(HttpStatus.UNAUTHORIZED, "해당 접근에 대한 권한이 없습니다."); private final HttpStatus status; private final String message; diff --git a/src/main/java/com/yourssu/roomescape/jwt/TokenExtractor.java b/src/main/java/com/yourssu/roomescape/jwt/TokenExtractor.java new file mode 100644 index 0000000..6eb075e --- /dev/null +++ b/src/main/java/com/yourssu/roomescape/jwt/TokenExtractor.java @@ -0,0 +1,26 @@ +package com.yourssu.roomescape.jwt; + +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; +import jakarta.servlet.http.Cookie; + +import java.util.Arrays; + +public class TokenExtractor { + + private TokenExtractor() { + // 객체 생성 방지 + } + + public static String extractTokenFromCookies(Cookie[] cookies) { + if (cookies == null) { + throw new CustomException(ErrorCode.COOKIE_NOT_FOUND); + } + + return Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .map(Cookie::getValue) + .findFirst() + .orElseThrow(() -> new CustomException(ErrorCode.TOKEN_NOT_FOUND)); + } +} diff --git a/src/test/java/com/yourssu/roomescape/MissionStepTest.java b/src/test/java/com/yourssu/roomescape/MissionStepTest.java index 38caa07..ad0dc3b 100644 --- a/src/test/java/com/yourssu/roomescape/MissionStepTest.java +++ b/src/test/java/com/yourssu/roomescape/MissionStepTest.java @@ -2,7 +2,6 @@ import com.yourssu.roomescape.auth.AuthService; import com.yourssu.roomescape.auth.LoginRequest; -import com.yourssu.roomescape.jwt.TokenProvider; import com.yourssu.roomescape.reservation.ReservationResponse; import io.restassured.RestAssured; import io.restassured.http.ContentType; @@ -87,4 +86,25 @@ public class MissionStepTest { assertThat(adminResponse.statusCode()).isEqualTo(201); assertThat(adminResponse.as(ReservationResponse.class).getName()).isEqualTo("브라운"); } + + @Test + void 삼단계() { + LoginRequest loginRequest = new LoginRequest("brown@email.com", "password"); + String brownToken = authService.login(loginRequest); + + RestAssured.given().log().all() + .cookie("token", brownToken) + .get("/admin") + .then().log().all() + .statusCode(401); + + loginRequest = new LoginRequest("admin@email.com", "password"); + String adminToken = authService.login(loginRequest); + + RestAssured.given().log().all() + .cookie("token", adminToken) + .get("/admin") + .then().log().all() + .statusCode(200); + } } From c6b861328fc845a5eb7b3bb7f723aa980ba7564c Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Wed, 16 Apr 2025 22:58:38 +0900 Subject: [PATCH 05/43] =?UTF-8?q?refactor:=20resolveArgument=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/roomescape/auth/LoginMemberArgumentResolver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java b/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java index bfd7718..a2d5f64 100644 --- a/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java +++ b/src/main/java/com/yourssu/roomescape/auth/LoginMemberArgumentResolver.java @@ -1,6 +1,7 @@ package com.yourssu.roomescape.auth; import com.yourssu.roomescape.jwt.TokenExtractor; +import com.yourssu.roomescape.member.Member; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; @@ -25,7 +26,7 @@ public boolean supportsParameter(MethodParameter parameter) { } @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + public Member resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); Cookie[] cookies = request.getCookies(); From 96b1a20d85ca8639f8e6348613e38df9bcae0e52 Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:50:23 +0900 Subject: [PATCH 06/43] =?UTF-8?q?refactor:=20=EC=BF=A0=ED=82=A4=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EA=B8=B0=EA=B0=84=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/auth/AdminAuthorizationInterceptor.java | 2 ++ .../java/com/yourssu/roomescape/auth/AuthController.java | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java b/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java index d640dc6..93ef923 100644 --- a/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java +++ b/src/main/java/com/yourssu/roomescape/auth/AdminAuthorizationInterceptor.java @@ -1,5 +1,7 @@ package com.yourssu.roomescape.auth; +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; import com.yourssu.roomescape.jwt.TokenExtractor; import com.yourssu.roomescape.member.Member; import jakarta.servlet.http.Cookie; diff --git a/src/main/java/com/yourssu/roomescape/auth/AuthController.java b/src/main/java/com/yourssu/roomescape/auth/AuthController.java index 2ff122c..21b8dbd 100644 --- a/src/main/java/com/yourssu/roomescape/auth/AuthController.java +++ b/src/main/java/com/yourssu/roomescape/auth/AuthController.java @@ -10,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.util.Arrays; + @RestController public class AuthController { @@ -20,20 +22,21 @@ public AuthController(AuthService authService) { } @PostMapping("/login") - public ResponseEntity login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) { + public ResponseEntity login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) { String accessToken = authService.login(loginRequest); Cookie cookie = new Cookie("token", accessToken); cookie.setHttpOnly(true); cookie.setPath("/"); - cookie.setMaxAge(0); response.addCookie(cookie); return ResponseEntity.ok().build(); } @GetMapping("/login/check") public ResponseEntity loginCheck(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + System.out.println(Arrays.toString(cookies)); String token = TokenExtractor.extractTokenFromCookies(cookies); String name = authService.checkLogin(token).getName(); From 1ae73794e09e918eeb70ebaa0ae0f534f82473a8 Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Fri, 18 Apr 2025 12:29:21 +0900 Subject: [PATCH 07/43] =?UTF-8?q?refactor:=20RowMapper=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/roomescape/member/MemberDao.java | 135 +++++++++--------- 1 file changed, 64 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/yourssu/roomescape/member/MemberDao.java b/src/main/java/com/yourssu/roomescape/member/MemberDao.java index 3a1166d..debe625 100644 --- a/src/main/java/com/yourssu/roomescape/member/MemberDao.java +++ b/src/main/java/com/yourssu/roomescape/member/MemberDao.java @@ -1,83 +1,76 @@ -package com.yourssu.roomescape.member; + package com.yourssu.roomescape.member; -import com.yourssu.roomescape.exception.CustomException; -import com.yourssu.roomescape.exception.ErrorCode; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; + import com.yourssu.roomescape.exception.CustomException; + import com.yourssu.roomescape.exception.ErrorCode; + import org.springframework.dao.DataAccessException; + import org.springframework.jdbc.core.JdbcTemplate; + import org.springframework.jdbc.core.RowMapper; + import org.springframework.jdbc.support.GeneratedKeyHolder; + import org.springframework.jdbc.support.KeyHolder; + import org.springframework.stereotype.Repository; -@Repository -public class MemberDao { - private JdbcTemplate jdbcTemplate; + @Repository + public class MemberDao { + private JdbcTemplate jdbcTemplate; - public MemberDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } + public MemberDao(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } - public Member save(Member member) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement("INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, member.getName()); - ps.setString(2, member.getEmail()); - ps.setString(3, member.getPassword()); - ps.setString(4, member.getRole()); - return ps; - }, keyHolder); + private final RowMapper memberRowMapper = (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("role") + ); - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); - } + public Member save(Member member) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(connection -> { + var ps = connection.prepareStatement("INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", new String[]{"id"}); + ps.setString(1, member.getName()); + ps.setString(2, member.getEmail()); + ps.setString(3, member.getPassword()); + ps.setString(4, member.getRole()); + return ps; + }, keyHolder); - public Member findByEmailAndPassword(String email, String password) { - try { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - email, password - ); - } catch (DataAccessException e) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); } - } - public Member findByEmail(String email) { - try { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - email - ); - } catch (DataAccessException e) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + public Member findByEmailAndPassword(String email, String password) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", + memberRowMapper, + email, password + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } + } + + public Member findByEmail(String email) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE email = ?", + memberRowMapper, + email + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } } - } - public Member findByName(String name) { - try { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - name - ); - } catch (DataAccessException e) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + public Member findByName(String name) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE name = ?", + memberRowMapper, + name + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } } } -} From 1215822434fe20a769ad4b2876ff1f28cb92c164 Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Fri, 18 Apr 2025 17:55:31 +0900 Subject: [PATCH 08/43] =?UTF-8?q?refactor:=20GlobalExceptionHandler=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=EC=9D=84=20=EC=9C=84=ED=95=B4=20=EC=83=81?= =?UTF-8?q?=EC=9C=84=20@ControllerAdvice=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/roomescape/ExceptionController.java | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 src/main/java/com/yourssu/roomescape/ExceptionController.java diff --git a/src/main/java/com/yourssu/roomescape/ExceptionController.java b/src/main/java/com/yourssu/roomescape/ExceptionController.java deleted file mode 100644 index 4bc38a3..0000000 --- a/src/main/java/com/yourssu/roomescape/ExceptionController.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.yourssu.roomescape; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - - -@ControllerAdvice -public class ExceptionController { - @ExceptionHandler(Exception.class) - public ResponseEntity handleRuntimeException(Exception e) { - e.printStackTrace(); - return ResponseEntity.badRequest().build(); - } -} From 5de5b639a7102c09691437a51977ed8dd1364851 Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Fri, 18 Apr 2025 18:34:29 +0900 Subject: [PATCH 09/43] =?UTF-8?q?refactor:=20=EC=98=88=EC=95=BD=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/exception/ErrorCode.java | 3 +- .../yourssu/roomescape/member/MemberDao.java | 130 +++++++++--------- .../reservation/ReservationController.java | 6 + .../reservation/ReservationService.java | 17 ++- 4 files changed, 83 insertions(+), 73 deletions(-) diff --git a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java index 311b9f7..8261c5a 100644 --- a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java +++ b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java @@ -8,7 +8,8 @@ public enum ErrorCode { TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키에 토큰이 존재하지 않습니다."), MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자의 정보를 찾을 수 없습니다."), INVALID_RESERVATION_REQUEST(HttpStatus.BAD_REQUEST, "예약 요청 값이 누락되었습니다."), - UNAUTHORIZED_ACCESS(HttpStatus.UNAUTHORIZED, "해당 접근에 대한 권한이 없습니다."); + UNAUTHORIZED_ACCESS(HttpStatus.FORBIDDEN, "해당 접근에 대한 권한이 없습니다."), + DUPLICATE_MEMBER_NAME_EXISTS(HttpStatus.INTERNAL_SERVER_ERROR, "중복된 이름이 존재합니다. 관리자에게 문의하세요."); private final HttpStatus status; private final String message; diff --git a/src/main/java/com/yourssu/roomescape/member/MemberDao.java b/src/main/java/com/yourssu/roomescape/member/MemberDao.java index debe625..8950465 100644 --- a/src/main/java/com/yourssu/roomescape/member/MemberDao.java +++ b/src/main/java/com/yourssu/roomescape/member/MemberDao.java @@ -1,76 +1,80 @@ - package com.yourssu.roomescape.member; +package com.yourssu.roomescape.member; - import com.yourssu.roomescape.exception.CustomException; - import com.yourssu.roomescape.exception.ErrorCode; - import org.springframework.dao.DataAccessException; - import org.springframework.jdbc.core.JdbcTemplate; - import org.springframework.jdbc.core.RowMapper; - import org.springframework.jdbc.support.GeneratedKeyHolder; - import org.springframework.jdbc.support.KeyHolder; - import org.springframework.stereotype.Repository; +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; - @Repository - public class MemberDao { - private JdbcTemplate jdbcTemplate; +import java.util.List; +import java.util.Optional; - public MemberDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } +@Repository +public class MemberDao { + private JdbcTemplate jdbcTemplate; - private final RowMapper memberRowMapper = (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ); + public MemberDao(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } - public Member save(Member member) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement("INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, member.getName()); - ps.setString(2, member.getEmail()); - ps.setString(3, member.getPassword()); - ps.setString(4, member.getRole()); - return ps; - }, keyHolder); + private final RowMapper memberRowMapper = (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("role") + ); - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); - } + public Member save(Member member) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(connection -> { + var ps = connection.prepareStatement("INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", new String[]{"id"}); + ps.setString(1, member.getName()); + ps.setString(2, member.getEmail()); + ps.setString(3, member.getPassword()); + ps.setString(4, member.getRole()); + return ps; + }, keyHolder); + + return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); + } - public Member findByEmailAndPassword(String email, String password) { - try { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", - memberRowMapper, - email, password - ); - } catch (DataAccessException e) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); - } + public Member findByEmailAndPassword(String email, String password) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", + memberRowMapper, + email, password + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); } + } - public Member findByEmail(String email) { - try { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ?", - memberRowMapper, - email - ); - } catch (DataAccessException e) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); - } + public Member findByEmail(String email) { + try { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE email = ?", + memberRowMapper, + email + ); + } catch (DataAccessException e) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); } + } - public Member findByName(String name) { - try { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", - memberRowMapper, - name - ); - } catch (DataAccessException e) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); - } + public Optional findByName(String name) { + List members = jdbcTemplate.query( + "SELECT id, name, email, role FROM member WHERE name = ?", + memberRowMapper, + name + ); + if (members.size() > 1) { + throw new CustomException(ErrorCode.DUPLICATE_MEMBER_NAME_EXISTS); } + + return members.isEmpty() ? Optional.empty() : Optional.of(members.get(0)); } +} diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java index 80f9854..fa4004a 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java @@ -1,6 +1,8 @@ package com.yourssu.roomescape.reservation; import com.yourssu.roomescape.auth.LoginMember; +import com.yourssu.roomescape.exception.CustomException; +import com.yourssu.roomescape.exception.ErrorCode; import com.yourssu.roomescape.member.Member; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -24,6 +26,10 @@ public List list() { @PostMapping("/reservations") public ResponseEntity create(@RequestBody ReservationRequest reservationRequest, @LoginMember Member member) { + if (reservationRequest.getDate() == null || reservationRequest.getTheme() == null || reservationRequest.getTime() == null) { + throw new CustomException(ErrorCode.INVALID_RESERVATION_REQUEST); + } + ReservationResponse reservation = reservationService.save(reservationRequest, member); return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java index 328c357..667b51e 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java @@ -20,17 +20,16 @@ public ReservationService(ReservationDao reservationDao, MemberDao memberDao) { } public ReservationResponse save(ReservationRequest reservationRequest, Member member) { - if (reservationRequest.getDate() == null || reservationRequest.getTheme() == null || reservationRequest.getTime() == null) { - throw new CustomException(ErrorCode.INVALID_RESERVATION_REQUEST); + String memberName = reservationRequest.getName(); + + if (memberName != null) { + Member existingMember = memberDao.findByName(memberName) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); + memberName = existingMember.getName(); + } else { + memberName = member.getName(); } - String memberName = Optional.ofNullable(reservationRequest.getName()) - .map(name -> { - Member existingMember = memberDao.findByName(name); - return existingMember.getName(); - }) - .orElse(member.getName()); - ReservationRequest updatedRequest = new ReservationRequest( memberName, reservationRequest.getDate(), From 15a68e8652c9515401fa8f61b678c63b3c6165fb Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Fri, 18 Apr 2025 19:00:50 +0900 Subject: [PATCH 10/43] =?UTF-8?q?refactor:=20@ExceptionHandler(Exception.c?= =?UTF-8?q?lass)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/roomescape/exception/ErrorCode.java | 1 + .../exception/GlobalExceptionHandler.java | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java index 8261c5a..090d449 100644 --- a/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java +++ b/src/main/java/com/yourssu/roomescape/exception/ErrorCode.java @@ -4,6 +4,7 @@ public enum ErrorCode { + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버에 문제가 생겼습니다."), COOKIE_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키가 존재하지 않습니다."), TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "쿠키에 토큰이 존재하지 않습니다."), MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "사용자의 정보를 찾을 수 없습니다."), diff --git a/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java b/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java index b9b2f99..d28b0b2 100644 --- a/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/yourssu/roomescape/exception/GlobalExceptionHandler.java @@ -1,5 +1,7 @@ package com.yourssu.roomescape.exception; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -7,8 +9,19 @@ @RestControllerAdvice public class GlobalExceptionHandler { + private final Logger log = LoggerFactory.getLogger(getClass()); + + @ExceptionHandler(Exception.class) + public ResponseEntity handleServerException(Exception e) { + log.warn(e.getMessage(), e); + ErrorCode errorCode = ErrorCode.INTERNAL_SERVER_ERROR; + ErrorResponse response = new ErrorResponse(errorCode.name(), errorCode.getMessage()); + return ResponseEntity.status(errorCode.getStatus()).body(response); + } + @ExceptionHandler(CustomException.class) public ResponseEntity handleCustomException(CustomException e) { + log.warn(e.getMessage(), e); ErrorCode errorCode = e.getErrorCode(); ErrorResponse response = new ErrorResponse(errorCode.name(), errorCode.getMessage()); return ResponseEntity.status(errorCode.getStatus()).body(response); From 9b8ad45fc08cf84e525ec8a2bba4af353599d33c Mon Sep 17 00:00:00 2001 From: yueunfive <122276414+yueunfive@users.noreply.github.com> Date: Fri, 18 Apr 2025 19:45:46 +0900 Subject: [PATCH 11/43] =?UTF-8?q?refactor:=20=EC=98=88=EC=95=BD=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reservation/ReservationController.java | 1 + .../reservation/ReservationDao.java | 26 ++++++---------- .../reservation/ReservationService.java | 31 +++++++++++++------ .../yourssu/roomescape/theme/ThemeDao.java | 6 ++++ .../com/yourssu/roomescape/time/TimeDao.java | 6 ++++ 5 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java index fa4004a..32fc9bf 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationController.java @@ -4,6 +4,7 @@ import com.yourssu.roomescape.exception.CustomException; import com.yourssu.roomescape.exception.ErrorCode; import com.yourssu.roomescape.member.Member; +import com.yourssu.roomescape.theme.ThemeDao; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationDao.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationDao.java index 5b643bb..6dec33f 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationDao.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationDao.java @@ -43,31 +43,23 @@ public List findAll() { ))); } - public Reservation save(ReservationRequest reservationRequest) { + public Reservation save(Reservation reservation) { KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(connection -> { PreparedStatement ps = connection.prepareStatement("INSERT INTO reservation(date, name, theme_id, time_id) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, reservationRequest.getDate()); - ps.setString(2, reservationRequest.getName()); - ps.setLong(3, reservationRequest.getTheme()); - ps.setLong(4, reservationRequest.getTime()); + ps.setString(1, reservation.getDate()); + ps.setString(2, reservation.getName()); + ps.setLong(3, reservation.getTheme().getId()); + ps.setLong(4, reservation.getTime().getId()); return ps; }, keyHolder); - Time time = jdbcTemplate.queryForObject("SELECT * FROM time WHERE id = ?", - (rs, rowNum) -> new Time(rs.getLong("id"), rs.getString("time_value")), - reservationRequest.getTime()); - - Theme theme = jdbcTemplate.queryForObject("SELECT * FROM theme WHERE id = ?", - (rs, rowNum) -> new Theme(rs.getLong("id"), rs.getString("name"), rs.getString("description")), - reservationRequest.getTheme()); - return new Reservation( keyHolder.getKey().longValue(), - reservationRequest.getName(), - reservationRequest.getDate(), - time, - theme + reservation.getName(), + reservation.getDate(), + reservation.getTime(), + reservation.getTheme() ); } diff --git a/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java b/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java index 667b51e..b2a00c0 100644 --- a/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java +++ b/src/main/java/com/yourssu/roomescape/reservation/ReservationService.java @@ -4,6 +4,10 @@ import com.yourssu.roomescape.exception.ErrorCode; import com.yourssu.roomescape.member.Member; import com.yourssu.roomescape.member.MemberDao; +import com.yourssu.roomescape.theme.Theme; +import com.yourssu.roomescape.theme.ThemeDao; +import com.yourssu.roomescape.time.Time; +import com.yourssu.roomescape.time.TimeDao; import org.springframework.stereotype.Service; import java.util.List; @@ -13,10 +17,14 @@ public class ReservationService { private final ReservationDao reservationDao; private final MemberDao memberDao; + private final ThemeDao themeDao; + private final TimeDao timeDao; - public ReservationService(ReservationDao reservationDao, MemberDao memberDao) { + public ReservationService(ReservationDao reservationDao, MemberDao memberDao, ThemeDao themeDao, TimeDao timeDao) { this.reservationDao = reservationDao; this.memberDao = memberDao; + this.themeDao = themeDao; + this.timeDao = timeDao; } public ReservationResponse save(ReservationRequest reservationRequest, Member member) { @@ -30,21 +38,24 @@ public ReservationResponse save(ReservationRequest reservationRequest, Member me memberName = member.getName(); } - ReservationRequest updatedRequest = new ReservationRequest( + Time time = timeDao.findById(reservationRequest.getTime()); + Theme theme = themeDao.findById(reservationRequest.getTheme()); + + Reservation reservation = new Reservation( memberName, reservationRequest.getDate(), - reservationRequest.getTheme(), - reservationRequest.getTime() + time, + theme ); - Reservation reservation = reservationDao.save(updatedRequest); + Reservation newReservation = reservationDao.save(reservation); return new ReservationResponse( - reservation.getId(), - reservation.getName(), - reservation.getTheme().getName(), - reservation.getDate(), - reservation.getTime().getValue()); + newReservation.getId(), + newReservation.getName(), + newReservation.getTheme().getName(), + newReservation.getDate(), + newReservation.getTime().getValue()); } public void deleteById(Long id) { diff --git a/src/main/java/com/yourssu/roomescape/theme/ThemeDao.java b/src/main/java/com/yourssu/roomescape/theme/ThemeDao.java index 6fcf67f..c519923 100644 --- a/src/main/java/com/yourssu/roomescape/theme/ThemeDao.java +++ b/src/main/java/com/yourssu/roomescape/theme/ThemeDao.java @@ -23,6 +23,12 @@ public List findAll() { )); } + public Theme findById(Long id) { + return jdbcTemplate.queryForObject("SELECT * FROM theme WHERE id = ?", + (rs, rowNum) -> new Theme(rs.getLong("id"), rs.getString("name"), rs.getString("description")), + id); + } + public Theme save(Theme theme) { KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(connection -> { diff --git a/src/main/java/com/yourssu/roomescape/time/TimeDao.java b/src/main/java/com/yourssu/roomescape/time/TimeDao.java index 7d45644..56edc58 100644 --- a/src/main/java/com/yourssu/roomescape/time/TimeDao.java +++ b/src/main/java/com/yourssu/roomescape/time/TimeDao.java @@ -24,6 +24,12 @@ public List