From e233cc25c4a2e0cc2709a19a75221f8b83ac8ca3 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 13:33:34 +0900 Subject: [PATCH 01/79] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/login/JwtUtil.java | 48 ++++++++++ .../roomescape/login/LoginController.java | 88 +++++++++++++++++++ .../roomescape/login/LoginRequestDto.java | 21 +++++ .../java/roomescape/login/LoginService.java | 4 + src/main/resources/application.properties | 3 +- src/test/java/roomescape/MissionStepTest.java | 14 ++- 6 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 src/main/java/roomescape/login/JwtUtil.java create mode 100644 src/main/java/roomescape/login/LoginController.java create mode 100644 src/main/java/roomescape/login/LoginRequestDto.java create mode 100644 src/main/java/roomescape/login/LoginService.java diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java new file mode 100644 index 00000000..3b06dfbc --- /dev/null +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -0,0 +1,48 @@ +package roomescape.login; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.spec.SecretKeySpec; +import java.security.Key; +import java.util.Date; + +@Component +public class JwtUtil { + @Value("${jwt.secret}") + private String secretKey; + + private Key key; + private static final long EXPIRATION_TIME = 86400000; + + @PostConstruct + public void init() { + if (secretKey == null) { + throw new IllegalStateException("SECRET_KEY가 초기화되지 않았습니다."); + } + key = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); + } + + // userId를 기반으로 JWT 생성 + public String generateToken(Long userId) { + return Jwts.builder() + .setSubject(String.valueOf(userId)) // userId를 주제(subject)로 설정 + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) + .signWith(key, SignatureAlgorithm.HS256) // 서명 알고리즘과 비밀 키 설정 + .compact(); + } + +// // 토큰에서 userId 추출 +// public Long getUserIdFromToken(String token) { +// return Long.parseLong(Jwts.parserBuilder() +// .setSigningKey(key) +// .build() +// .parseClaimsJws(token) +// .getBody() +// .getSubject()); +// } +} diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java new file mode 100644 index 00000000..ca45a884 --- /dev/null +++ b/src/main/java/roomescape/login/LoginController.java @@ -0,0 +1,88 @@ +package roomescape.login; + +import com.fasterxml.jackson.databind.JsonNode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; +import roomescape.member.Member; +import roomescape.member.MemberDao; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/login") +public class LoginController { + @Autowired + private JwtUtil jwtUtil; + @Autowired + private MemberDao memberDao; + + @PostMapping + public ResponseEntity> login(@RequestBody LoginRequestDto loginRequestDto, HttpServletResponse response) { + String email = loginRequestDto.getEmail(); + String password = loginRequestDto.getPassword(); + + // 데이터베이스에서 사용자 조회 + Member member = memberDao.findByEmailAndPassword(email, password); + + if (member != null) { + // JWT 토큰 생성 + String token = jwtUtil.generateToken(member.getId()); + + // Cookie에 토큰 추가 + Cookie cookie = new Cookie("token", token); + cookie.setHttpOnly(true); + cookie.setPath("/"); + response.addCookie(cookie); + + System.out.println(member.getName()); + + // 헤더 설정 + response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + response.setHeader(HttpHeaders.CONNECTION, "Keep-Alive"); + response.setHeader("Keep-Alive", "timeout=60"); + + // 응답 본문에 토큰 추가 + Map responseBody = new HashMap<>(); + responseBody.put("token", token); + responseBody.put("message", "Login successful"); + + return ResponseEntity.ok(responseBody); + } + // 인증 실패 메시지 포함 + Map errorResponse = new HashMap<>(); + errorResponse.put("message", "Invalid email or password"); + + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); + } + + @GetMapping("/check") + public ResponseEntity> checkLogin(@CookieValue(name = "token", required = false) String token) { + if (token == null || token.isEmpty()) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + try { + // JWT 토큰에서 사용자 ID 추출 + Long userId = jwtUtil.getUserIdFromToken(token); + + // 데이터베이스에서 사용자 조회 + Member member = memberDao.findByName(userId.toString()); + + // 응답 데이터 생성 + Map response = new HashMap<>(); + response.put("name", member.getName()); + response.put("role", member.getRole()); + + return ResponseEntity.ok(response); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + } +} diff --git a/src/main/java/roomescape/login/LoginRequestDto.java b/src/main/java/roomescape/login/LoginRequestDto.java new file mode 100644 index 00000000..97ab4931 --- /dev/null +++ b/src/main/java/roomescape/login/LoginRequestDto.java @@ -0,0 +1,21 @@ +package roomescape.login; + +public class LoginRequestDto { + private String email; + private String password; + + public LoginRequestDto() {} + + public LoginRequestDto(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/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java new file mode 100644 index 00000000..8c482dca --- /dev/null +++ b/src/main/java/roomescape/login/LoginService.java @@ -0,0 +1,4 @@ +package roomescape.login; + +public class LoginService { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a0f33bba..b7e470c4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,10 +2,11 @@ spring.sql.init.encoding=utf-8 spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.datasource.url=jdbc:h2:mem:database +jwt.secret=${JWT_SECRET_KEY} #spring.jpa.show-sql=true #spring.jpa.properties.hibernate.format_sql=true #spring.jpa.ddl-auto=create-drop #spring.jpa.defer-datasource-initialization=true -#roomescape.auth.jwt.secret= Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E= \ No newline at end of file +#roomescape.auth.jwt.secret= Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E= diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 6add784b..73856f00 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -16,7 +16,6 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) public class MissionStepTest { - @Test void 일단계() { Map params = new HashMap<>(); @@ -32,7 +31,16 @@ public class MissionStepTest { .extract(); 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("어드민"); } -} \ No newline at end of file +} From b043419cf6855db3515343e36f046febd4d0f360 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 14:12:30 +0900 Subject: [PATCH 02/79] =?UTF-8?q?feat=20:=201=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=ED=86=B5=EA=B3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../login/HandlerMethodArgumentResolver.java | 4 ++ src/main/java/roomescape/login/JwtUtil.java | 26 ++++--- .../roomescape/login/LoginController.java | 69 +++++++++---------- .../java/roomescape/member/MemberDao.java | 14 ++++ src/test/java/roomescape/MissionStepTest.java | 51 ++++++++++++++ 5 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 src/main/java/roomescape/login/HandlerMethodArgumentResolver.java diff --git a/src/main/java/roomescape/login/HandlerMethodArgumentResolver.java b/src/main/java/roomescape/login/HandlerMethodArgumentResolver.java new file mode 100644 index 00000000..68a760d9 --- /dev/null +++ b/src/main/java/roomescape/login/HandlerMethodArgumentResolver.java @@ -0,0 +1,4 @@ +package roomescape.login; + +public class HandlerMethodArgumentResolver { +} diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index 3b06dfbc..af1a3ce7 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -29,20 +29,24 @@ public void init() { // userId를 기반으로 JWT 생성 public String generateToken(Long userId) { return Jwts.builder() - .setSubject(String.valueOf(userId)) // userId를 주제(subject)로 설정 + .setSubject(String.valueOf(userId)) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) - .signWith(key, SignatureAlgorithm.HS256) // 서명 알고리즘과 비밀 키 설정 + .signWith(key, SignatureAlgorithm.HS256) .compact(); } -// // 토큰에서 userId 추출 -// public Long getUserIdFromToken(String token) { -// return Long.parseLong(Jwts.parserBuilder() -// .setSigningKey(key) -// .build() -// .parseClaimsJws(token) -// .getBody() -// .getSubject()); -// } + public Long getUserIdFromToken(String token) { + try { + String subject = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody() + .getSubject(); + return Long.valueOf(subject); + } catch (Exception e) { + throw new IllegalArgumentException("유효하지 않은 토큰입니다.", e); + } + } } diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index ca45a884..e7eb364b 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -1,14 +1,13 @@ package roomescape.login; -import com.fasterxml.jackson.databind.JsonNode; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletResponse; import roomescape.member.Member; import roomescape.member.MemberDao; @@ -27,35 +26,32 @@ public class LoginController { public ResponseEntity> login(@RequestBody LoginRequestDto loginRequestDto, HttpServletResponse response) { String email = loginRequestDto.getEmail(); String password = loginRequestDto.getPassword(); - - // 데이터베이스에서 사용자 조회 - Member member = memberDao.findByEmailAndPassword(email, password); - - if (member != null) { - // JWT 토큰 생성 - String token = jwtUtil.generateToken(member.getId()); - - // Cookie에 토큰 추가 - Cookie cookie = new Cookie("token", token); - cookie.setHttpOnly(true); - cookie.setPath("/"); - response.addCookie(cookie); - - System.out.println(member.getName()); - - // 헤더 설정 - response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - response.setHeader(HttpHeaders.CONNECTION, "Keep-Alive"); - response.setHeader("Keep-Alive", "timeout=60"); - - // 응답 본문에 토큰 추가 - Map responseBody = new HashMap<>(); - responseBody.put("token", token); - responseBody.put("message", "Login successful"); - - return ResponseEntity.ok(responseBody); + try { + Member member = memberDao.findByEmailAndPassword(email, password); + + if (member != null) { + String token = jwtUtil.generateToken(member.getId()); + + Cookie cookie = new Cookie("token", token); + cookie.setHttpOnly(true); + cookie.setPath("/"); + response.addCookie(cookie); + + response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + response.setHeader(HttpHeaders.CONNECTION, "Keep-Alive"); + response.setHeader("Keep-Alive", "timeout=60"); + + Map responseBody = new HashMap<>(); + responseBody.put("token", token); + responseBody.put("message", "Login successful"); + + return ResponseEntity.ok(responseBody); + } + } catch (EmptyResultDataAccessException e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("message", "Invalid email or password"); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); } - // 인증 실패 메시지 포함 Map errorResponse = new HashMap<>(); errorResponse.put("message", "Invalid email or password"); @@ -69,16 +65,15 @@ public ResponseEntity> checkLogin(@CookieValue(name = "token } try { - // JWT 토큰에서 사용자 ID 추출 Long userId = jwtUtil.getUserIdFromToken(token); + Member member = memberDao.findById(userId); - // 데이터베이스에서 사용자 조회 - Member member = memberDao.findByName(userId.toString()); + if (member == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } - // 응답 데이터 생성 Map response = new HashMap<>(); response.put("name", member.getName()); - response.put("role", member.getRole()); return ResponseEntity.ok(response); } catch (Exception e) { diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java index 81f77f4c..80d2bd30 100644 --- a/src/main/java/roomescape/member/MemberDao.java +++ b/src/main/java/roomescape/member/MemberDao.java @@ -52,4 +52,18 @@ public Member findByName(String name) { name ); } + + public Member findById(Long id) { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, role FROM member WHERE id = ?", + (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("role") + ), + id + ); + } + } diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 73856f00..ccd20a01 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; +import roomescape.reservation.ReservationResponse; import java.util.HashMap; import java.util.Map; @@ -43,4 +44,54 @@ public class MissionStepTest { assertThat(checkResponse.body().jsonPath().getString("name")).isEqualTo("어드민"); } + + private String createToken(String email, String password) { + Map params = new HashMap<>(); + params.put("email", email); + params.put("password", password); + + ExtractableResponse response = RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/login") + .then().log().all() + .statusCode(200) + .extract(); + + return response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; + } + + @Test + void 이단계() { + String token = createToken("admin@email.com", "password"); // 일단계에서 토큰을 추출하는 로직을 메서드로 따로 만들어서 활용하세요. + + 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 f7a3a4be51fc0cbdfc2f06338e044aa4da5c9db3 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 14:39:25 +0900 Subject: [PATCH 03/79] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../login/HandlerMethodArgumentResolver.java | 4 -- src/main/java/roomescape/login/JwtUtil.java | 1 - .../roomescape/login/LoginController.java | 43 +++++-------------- .../java/roomescape/login/LoginService.java | 37 ++++++++++++++++ 4 files changed, 47 insertions(+), 38 deletions(-) delete mode 100644 src/main/java/roomescape/login/HandlerMethodArgumentResolver.java diff --git a/src/main/java/roomescape/login/HandlerMethodArgumentResolver.java b/src/main/java/roomescape/login/HandlerMethodArgumentResolver.java deleted file mode 100644 index 68a760d9..00000000 --- a/src/main/java/roomescape/login/HandlerMethodArgumentResolver.java +++ /dev/null @@ -1,4 +0,0 @@ -package roomescape.login; - -public class HandlerMethodArgumentResolver { -} diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index af1a3ce7..6674e578 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -26,7 +26,6 @@ public void init() { key = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); } - // userId를 기반으로 JWT 생성 public String generateToken(Long userId) { return Jwts.builder() .setSubject(String.valueOf(userId)) diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index e7eb364b..198b2b70 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -3,8 +3,6 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -21,49 +19,28 @@ public class LoginController { private JwtUtil jwtUtil; @Autowired private MemberDao memberDao; + @Autowired + private LoginService loginService; @PostMapping public ResponseEntity> login(@RequestBody LoginRequestDto loginRequestDto, HttpServletResponse response) { - String email = loginRequestDto.getEmail(); - String password = loginRequestDto.getPassword(); try { - Member member = memberDao.findByEmailAndPassword(email, password); - - if (member != null) { - String token = jwtUtil.generateToken(member.getId()); - - Cookie cookie = new Cookie("token", token); - cookie.setHttpOnly(true); - cookie.setPath("/"); - response.addCookie(cookie); + String token = loginService.authenticate(loginRequestDto.getEmail(), loginRequestDto.getPassword()); - response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - response.setHeader(HttpHeaders.CONNECTION, "Keep-Alive"); - response.setHeader("Keep-Alive", "timeout=60"); + Cookie cookie = loginService.createAuthCookie(token); + response.addCookie(cookie); + Map responseBody = loginService.createLoginResponse(token); - Map responseBody = new HashMap<>(); - responseBody.put("token", token); - responseBody.put("message", "Login successful"); - - return ResponseEntity.ok(responseBody); - } - } catch (EmptyResultDataAccessException e) { + return ResponseEntity.ok(responseBody); + } catch (IllegalArgumentException e) { Map errorResponse = new HashMap<>(); - errorResponse.put("message", "Invalid email or password"); + errorResponse.put("message", e.getMessage()); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); } - Map errorResponse = new HashMap<>(); - errorResponse.put("message", "Invalid email or password"); - - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); } @GetMapping("/check") - public ResponseEntity> checkLogin(@CookieValue(name = "token", required = false) String token) { - if (token == null || token.isEmpty()) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - + public ResponseEntity> checkLogin(@CookieValue(name = "token", required = true) String token) { try { Long userId = jwtUtil.getUserIdFromToken(token); Member member = memberDao.findById(userId); diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index 8c482dca..b02a7b5d 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -1,4 +1,41 @@ package roomescape.login; +import jakarta.servlet.http.Cookie; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import roomescape.member.Member; +import roomescape.member.MemberDao; + +import java.util.HashMap; +import java.util.Map; + +@Service public class LoginService { + + @Autowired + private JwtUtil jwtUtil; + @Autowired + private MemberDao memberDao; + + public String authenticate(String email, String password) { + Member member = memberDao.findByEmailAndPassword(email, password); + if (member == null) { + throw new IllegalArgumentException("Invalid email or password"); + } + return jwtUtil.generateToken(member.getId()); + } + + public Cookie createAuthCookie(String token) { + Cookie cookie = new Cookie("token", token); + cookie.setHttpOnly(true); + cookie.setPath("/"); + return cookie; + } + + public Map createLoginResponse(String token) { + Map responseBody = new HashMap<>(); + responseBody.put("token", token); + responseBody.put("message", "Login successful"); + return responseBody; + } } From 7a17aa9574ac9c4be46b32bb7c031413f7c20150 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 17:09:04 +0900 Subject: [PATCH 04/79] =?UTF-8?q?feat=20:=20=EC=9D=B4=EB=A6=84=EC=97=86?= =?UTF-8?q?=EC=9D=B4=20=ED=9A=8C=EC=9B=90=EC=A0=95=EB=B3=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reservation/ReservationController.java | 33 +++++++++++++------ .../reservation/ReservationRequest.java | 4 +++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index b3bef399..2949e5de 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -1,18 +1,22 @@ package roomescape.reservation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import roomescape.login.JwtUtil; +import roomescape.member.MemberDao; +import roomescape.member.Member; import java.net.URI; import java.util.List; @RestController public class ReservationController { + @Autowired + private JwtUtil jwtUtil; + @Autowired + private MemberDao memberDao; private final ReservationService reservationService; @@ -26,18 +30,27 @@ public List list() { } @PostMapping("/reservations") - public ResponseEntity create(@RequestBody ReservationRequest reservationRequest) { - if (reservationRequest.getName() == null - || reservationRequest.getDate() == null + public ResponseEntity create(@CookieValue(name = "token", required = true) String token, @RequestBody ReservationRequest reservationRequest) { + if (reservationRequest.getDate() == null || reservationRequest.getTheme() == null || reservationRequest.getTime() == null) { return ResponseEntity.badRequest().build(); } - ReservationResponse reservation = reservationService.save(reservationRequest); + if (reservationRequest.getName() == null) { + Long userId = jwtUtil.getUserIdFromToken(token); + Member member = memberDao.findById(userId); + if (member == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + reservationRequest.setName(member.getName()); + } + + ReservationResponse reservation = reservationService.save(reservationRequest); return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); } + @DeleteMapping("/reservations/{id}") public ResponseEntity delete(@PathVariable Long id) { reservationService.deleteById(id); diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index 19f44124..a07a8483 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -21,4 +21,8 @@ public Long getTheme() { public Long getTime() { return time; } + + public void setName(String name) { + this.name = name; + } } From aa8ee73faaed0c24ede6cff4e49931b19d2a3ce9 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 17:12:31 +0900 Subject: [PATCH 05/79] =?UTF-8?q?refactor=20:=20reservationController=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/reservation/ReservationController.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 2949e5de..1742be30 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -12,6 +12,7 @@ import java.util.List; @RestController +@RequestMapping("/reservations") public class ReservationController { @Autowired private JwtUtil jwtUtil; @@ -24,12 +25,12 @@ public ReservationController(ReservationService reservationService) { this.reservationService = reservationService; } - @GetMapping("/reservations") + @GetMapping public List list() { return reservationService.findAll(); } - @PostMapping("/reservations") + @PostMapping public ResponseEntity create(@CookieValue(name = "token", required = true) String token, @RequestBody ReservationRequest reservationRequest) { if (reservationRequest.getDate() == null || reservationRequest.getTheme() == null @@ -51,7 +52,7 @@ public ResponseEntity create(@CookieValue(name = "token", required = true) Strin } - @DeleteMapping("/reservations/{id}") + @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable Long id) { reservationService.deleteById(id); return ResponseEntity.noContent().build(); From 9cff672bf76580e57895e40caef5a48c7ff33643 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 17:53:12 +0900 Subject: [PATCH 06/79] =?UTF-8?q?feat=20:=20=EA=B6=8C=ED=95=9C=EC=9D=B4=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20=EC=9E=90=EB=A7=8C=20=EC=A0=91=EA=B7=BC?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/login/AdminInterceptor.java | 59 +++++++++++++++++++ src/main/java/roomescape/login/JwtUtil.java | 12 +++- .../java/roomescape/login/LoginService.java | 13 +++- src/main/java/roomescape/login/WebConfig.java | 21 +++++++ src/test/java/roomescape/MissionStepTest.java | 19 ++++++ 5 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/main/java/roomescape/login/AdminInterceptor.java create mode 100644 src/main/java/roomescape/login/WebConfig.java diff --git a/src/main/java/roomescape/login/AdminInterceptor.java b/src/main/java/roomescape/login/AdminInterceptor.java new file mode 100644 index 00000000..8196a80d --- /dev/null +++ b/src/main/java/roomescape/login/AdminInterceptor.java @@ -0,0 +1,59 @@ +package roomescape.login; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import roomescape.member.Member; +import roomescape.member.MemberDao; + +@Component +public class AdminInterceptor implements HandlerInterceptor { + + @Autowired + private MemberDao memberDao; + + @Autowired + private JwtUtil jwtUtil; + + public AdminInterceptor(JwtUtil jwtUtil) { + this.jwtUtil = jwtUtil; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String token = null; + + if (request.getCookies() != null) { + for (var cookie : request.getCookies()) { + if ("token".equals(cookie.getName())) { + token = cookie.getValue(); + break; + } + } + } + + if (token == null) { + response.setStatus(401); + return false; + } + + try { + Long userId = jwtUtil.getUserIdFromToken(token); + Member member = memberDao.findById(userId); + + if (member == null || !"ADMIN".equals(member.getRole())) { + response.setStatus(401); + return false; + } + } catch (Exception e) { + response.setStatus(401); // 예외 발생 시 Unauthorized + return false; + } + + return true; + } + + +} diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index 6674e578..9adc2a89 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -1,5 +1,6 @@ package roomescape.login; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import jakarta.annotation.PostConstruct; @@ -26,9 +27,10 @@ public void init() { key = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); } - public String generateToken(Long userId) { + public String generateToken(Long userId, String role) { return Jwts.builder() .setSubject(String.valueOf(userId)) + .claim("role", role) // 역할 정보 추가 .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(key, SignatureAlgorithm.HS256) @@ -48,4 +50,12 @@ public Long getUserIdFromToken(String token) { throw new IllegalArgumentException("유효하지 않은 토큰입니다.", e); } } + + public Claims getClaimsFromToken(String token) { + return Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); + } } diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index b02a7b5d..cb2c7239 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -17,14 +17,25 @@ public class LoginService { @Autowired private MemberDao memberDao; +// public String authenticate(String email, String password) { +// Member member = memberDao.findByEmailAndPassword(email, password); +// if (member == null) { +// throw new IllegalArgumentException("Invalid email or password"); +// } +// return jwtUtil.generateToken(member.getId()); +// } + public String authenticate(String email, String password) { Member member = memberDao.findByEmailAndPassword(email, password); if (member == null) { throw new IllegalArgumentException("Invalid email or password"); } - return jwtUtil.generateToken(member.getId()); + + String role = member.getRole(); // 사용자의 역할 가져오기 + return jwtUtil.generateToken(member.getId(), role); // 역할 포함 } + public Cookie createAuthCookie(String token) { Cookie cookie = new Cookie("token", token); cookie.setHttpOnly(true); diff --git a/src/main/java/roomescape/login/WebConfig.java b/src/main/java/roomescape/login/WebConfig.java new file mode 100644 index 00000000..7d7facfc --- /dev/null +++ b/src/main/java/roomescape/login/WebConfig.java @@ -0,0 +1,21 @@ +package roomescape.login; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + private final AdminInterceptor adminInterceptor; + + public WebConfig(AdminInterceptor adminInterceptor) { + this.adminInterceptor = adminInterceptor; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(adminInterceptor) + .addPathPatterns("/admin"); + } +} diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index ccd20a01..353db353 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -94,4 +94,23 @@ private String createToken(String email, String password) { assertThat(adminResponse.statusCode()).isEqualTo(201); assertThat(adminResponse.as(ReservationResponse.class).getName()).isEqualTo("브라운"); } + + @Test + void 삼단계() { + String brownToken = createToken("brown@email.com", "password"); + + RestAssured.given().log().all() + .cookie("token", brownToken) + .get("/admin") + .then().log().all() + .statusCode(401); + + String adminToken = createToken("admin@email.com", "password"); + + RestAssured.given().log().all() + .cookie("token", adminToken) + .get("/admin") + .then().log().all() + .statusCode(200); + } } From 6be6af31fca77aed4286d7906537b03fd3452e3c Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 18:10:52 +0900 Subject: [PATCH 07/79] =?UTF-8?q?feat=20:=20=EA=B6=8C=ED=95=9C=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/login/AdminInterceptor.java | 37 +++++++++---------- src/main/java/roomescape/login/JwtUtil.java | 2 +- .../java/roomescape/login/LoginService.java | 14 +------ 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/main/java/roomescape/login/AdminInterceptor.java b/src/main/java/roomescape/login/AdminInterceptor.java index 8196a80d..dde8cb6c 100644 --- a/src/main/java/roomescape/login/AdminInterceptor.java +++ b/src/main/java/roomescape/login/AdminInterceptor.java @@ -1,5 +1,6 @@ package roomescape.login; +import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; @@ -10,10 +11,8 @@ @Component public class AdminInterceptor implements HandlerInterceptor { - @Autowired private MemberDao memberDao; - @Autowired private JwtUtil jwtUtil; @@ -25,35 +24,33 @@ public AdminInterceptor(JwtUtil jwtUtil) { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = null; - if (request.getCookies() != null) { - for (var cookie : request.getCookies()) { - if ("token".equals(cookie.getName())) { - token = cookie.getValue(); - break; - } - } - } + Cookie[] cookies = request.getCookies(); + token = extractTokenFromCookies(cookies); if (token == null) { response.setStatus(401); return false; } - try { - Long userId = jwtUtil.getUserIdFromToken(token); - Member member = memberDao.findById(userId); + Long userId = jwtUtil.getUserIdFromToken(token); + Member member = memberDao.findById(userId); - if (member == null || !"ADMIN".equals(member.getRole())) { - response.setStatus(401); - return false; - } - } catch (Exception e) { - response.setStatus(401); // 예외 발생 시 Unauthorized + if (member == null || !"ADMIN".equals(member.getRole())) { + response.setStatus(401); return false; } return true; } - + private String extractTokenFromCookies(Cookie[] cookies) { + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("token".equals(cookie.getName())) { + return cookie.getValue(); + } + } + } + return null; + } } diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index 9adc2a89..5b4ab904 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -30,7 +30,7 @@ public void init() { public String generateToken(Long userId, String role) { return Jwts.builder() .setSubject(String.valueOf(userId)) - .claim("role", role) // 역할 정보 추가 + .claim("role", role) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(key, SignatureAlgorithm.HS256) diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index cb2c7239..88476067 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -11,31 +11,21 @@ @Service public class LoginService { - @Autowired private JwtUtil jwtUtil; @Autowired private MemberDao memberDao; -// public String authenticate(String email, String password) { -// Member member = memberDao.findByEmailAndPassword(email, password); -// if (member == null) { -// throw new IllegalArgumentException("Invalid email or password"); -// } -// return jwtUtil.generateToken(member.getId()); -// } - public String authenticate(String email, String password) { Member member = memberDao.findByEmailAndPassword(email, password); if (member == null) { throw new IllegalArgumentException("Invalid email or password"); } - String role = member.getRole(); // 사용자의 역할 가져오기 - return jwtUtil.generateToken(member.getId(), role); // 역할 포함 + String role = member.getRole(); + return jwtUtil.generateToken(member.getId(), role); } - public Cookie createAuthCookie(String token) { Cookie cookie = new Cookie("token", token); cookie.setHttpOnly(true); From 9f11631b2941a2a8af6b18d5c02faeef3d4d5fe9 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 25 Dec 2024 19:14:35 +0900 Subject: [PATCH 08/79] =?UTF-8?q?refactor=20:=20=EC=95=88=20=EC=93=B0?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=A7=80=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\202\274\353\213\250\352\263\204.run.xml" | 31 +++++++++++++++++++ src/main/java/roomescape/login/JwtUtil.java | 8 ----- 2 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 ".run/MissionStepTest.\354\202\274\353\213\250\352\263\204.run.xml" diff --git "a/.run/MissionStepTest.\354\202\274\353\213\250\352\263\204.run.xml" "b/.run/MissionStepTest.\354\202\274\353\213\250\352\263\204.run.xml" new file mode 100644 index 00000000..80b29a46 --- /dev/null +++ "b/.run/MissionStepTest.\354\202\274\353\213\250\352\263\204.run.xml" @@ -0,0 +1,31 @@ + + + + + + + + false + true + false + true + + + \ No newline at end of file diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index 5b4ab904..5aa79ca3 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -50,12 +50,4 @@ public Long getUserIdFromToken(String token) { throw new IllegalArgumentException("유효하지 않은 토큰입니다.", e); } } - - public Claims getClaimsFromToken(String token) { - return Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .getBody(); - } } From 56723c73c2068b7fa7138f5308515787338f66c7 Mon Sep 17 00:00:00 2001 From: hyebin Date: Thu, 2 Jan 2025 06:33:29 +0900 Subject: [PATCH 09/79] =?UTF-8?q?refactor=20:=20=EC=95=88=20=EC=93=B0?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=A7=80=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/{login => member/right}/AdminInterceptor.java | 3 ++- .../java/roomescape/{login => member/right}/WebConfig.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) rename src/main/java/roomescape/{login => member/right}/AdminInterceptor.java (96%) rename src/main/java/roomescape/{login => member/right}/WebConfig.java (95%) diff --git a/src/main/java/roomescape/login/AdminInterceptor.java b/src/main/java/roomescape/member/right/AdminInterceptor.java similarity index 96% rename from src/main/java/roomescape/login/AdminInterceptor.java rename to src/main/java/roomescape/member/right/AdminInterceptor.java index dde8cb6c..3ab839c1 100644 --- a/src/main/java/roomescape/login/AdminInterceptor.java +++ b/src/main/java/roomescape/member/right/AdminInterceptor.java @@ -1,4 +1,4 @@ -package roomescape.login; +package roomescape.member.right; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; +import roomescape.login.JwtUtil; import roomescape.member.Member; import roomescape.member.MemberDao; diff --git a/src/main/java/roomescape/login/WebConfig.java b/src/main/java/roomescape/member/right/WebConfig.java similarity index 95% rename from src/main/java/roomescape/login/WebConfig.java rename to src/main/java/roomescape/member/right/WebConfig.java index 7d7facfc..892ca173 100644 --- a/src/main/java/roomescape/login/WebConfig.java +++ b/src/main/java/roomescape/member/right/WebConfig.java @@ -1,4 +1,4 @@ -package roomescape.login; +package roomescape.member.right; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; From 9db83a89d4c86f2eda9df8202d06de6ccbad1247 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 02:08:10 +0900 Subject: [PATCH 10/79] =?UTF-8?q?refactor=20:=20=EC=95=88=20=EC=93=B0?= =?UTF-8?q?=EB=8A=94=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A7=80=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/login/JwtUtil.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index 5aa79ca3..96fd9d41 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -1,6 +1,5 @@ package roomescape.login; -import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import jakarta.annotation.PostConstruct; @@ -21,9 +20,6 @@ public class JwtUtil { @PostConstruct public void init() { - if (secretKey == null) { - throw new IllegalStateException("SECRET_KEY가 초기화되지 않았습니다."); - } key = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); } From 3cb415382f580232624e57241eba1b25f466b4eb Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 04:19:27 +0900 Subject: [PATCH 11/79] =?UTF-8?q?refactor=20:=20key=EB=A5=BC=20=EC=A7=80?= =?UTF-8?q?=EC=97=AD=EB=B3=80=EC=88=98=EB=A1=9C=20=EB=B0=94=EA=BE=B8?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/login/JwtUtil.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/login/JwtUtil.java index 96fd9d41..621f32e5 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/login/JwtUtil.java @@ -2,7 +2,6 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -15,15 +14,14 @@ public class JwtUtil { @Value("${jwt.secret}") private String secretKey; - private Key key; private static final long EXPIRATION_TIME = 86400000; - @PostConstruct - public void init() { - key = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); + private Key generateKey() { + return new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); } public String generateToken(Long userId, String role) { + Key key = generateKey(); return Jwts.builder() .setSubject(String.valueOf(userId)) .claim("role", role) @@ -35,6 +33,7 @@ public String generateToken(Long userId, String role) { public Long getUserIdFromToken(String token) { try { + Key key = generateKey(); String subject = Jwts.parserBuilder() .setSigningKey(key) .build() From 7fbcc725e089c6731bdf1939e95a310de4ff5099 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 04:28:15 +0900 Subject: [PATCH 12/79] =?UTF-8?q?refactor=20:=20jwtService=EB=A1=9C=20user?= =?UTF-8?q?Id=20=EC=B0=BE=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=98=AE?= =?UTF-8?q?=EA=B8=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/jwt/JwtService.java | 21 +++++++++++++++++++ .../roomescape/{login => jwt}/JwtUtil.java | 11 +++++----- .../roomescape/login/LoginController.java | 5 +++-- .../java/roomescape/login/LoginService.java | 1 + .../member/right/AdminInterceptor.java | 7 +++++-- .../reservation/ReservationController.java | 7 +++++-- 6 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 src/main/java/roomescape/jwt/JwtService.java rename src/main/java/roomescape/{login => jwt}/JwtUtil.java (84%) diff --git a/src/main/java/roomescape/jwt/JwtService.java b/src/main/java/roomescape/jwt/JwtService.java new file mode 100644 index 00000000..5d4c9fdd --- /dev/null +++ b/src/main/java/roomescape/jwt/JwtService.java @@ -0,0 +1,21 @@ +package roomescape.jwt; + +import io.jsonwebtoken.Claims; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JwtService { + @Autowired + private JwtUtil jwtUtil; + + public Long getUserIdFromToken(String token) { + Claims claims = jwtUtil.getClaimsFromToken(token); + try { + return Long.valueOf(claims.getSubject()); + } catch (Exception e) { + throw new IllegalArgumentException("Claims에서 User ID를 추출할 수 없습니다.", e); + } + } +} + diff --git a/src/main/java/roomescape/login/JwtUtil.java b/src/main/java/roomescape/jwt/JwtUtil.java similarity index 84% rename from src/main/java/roomescape/login/JwtUtil.java rename to src/main/java/roomescape/jwt/JwtUtil.java index 621f32e5..0ed71a26 100644 --- a/src/main/java/roomescape/login/JwtUtil.java +++ b/src/main/java/roomescape/jwt/JwtUtil.java @@ -1,5 +1,6 @@ -package roomescape.login; +package roomescape.jwt; +import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; @@ -31,16 +32,14 @@ public String generateToken(Long userId, String role) { .compact(); } - public Long getUserIdFromToken(String token) { + public Claims getClaimsFromToken(String token) { try { Key key = generateKey(); - String subject = Jwts.parserBuilder() + return Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) - .getBody() - .getSubject(); - return Long.valueOf(subject); + .getBody(); } catch (Exception e) { throw new IllegalArgumentException("유효하지 않은 토큰입니다.", e); } diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index 198b2b70..0445eb34 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -6,6 +6,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import roomescape.jwt.JwtService; import roomescape.member.Member; import roomescape.member.MemberDao; @@ -16,7 +17,7 @@ @RequestMapping("/login") public class LoginController { @Autowired - private JwtUtil jwtUtil; + private JwtService jwtService; @Autowired private MemberDao memberDao; @Autowired @@ -42,7 +43,7 @@ public ResponseEntity> login(@RequestBody LoginRequestDto lo @GetMapping("/check") public ResponseEntity> checkLogin(@CookieValue(name = "token", required = true) String token) { try { - Long userId = jwtUtil.getUserIdFromToken(token); + Long userId = jwtService.getUserIdFromToken(token); Member member = memberDao.findById(userId); if (member == null) { diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index 88476067..c7f6c9f8 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -3,6 +3,7 @@ import jakarta.servlet.http.Cookie; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import roomescape.jwt.JwtUtil; import roomescape.member.Member; import roomescape.member.MemberDao; diff --git a/src/main/java/roomescape/member/right/AdminInterceptor.java b/src/main/java/roomescape/member/right/AdminInterceptor.java index 3ab839c1..8dbbfa30 100644 --- a/src/main/java/roomescape/member/right/AdminInterceptor.java +++ b/src/main/java/roomescape/member/right/AdminInterceptor.java @@ -6,7 +6,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import roomescape.login.JwtUtil; +import roomescape.jwt.JwtService; +import roomescape.jwt.JwtUtil; import roomescape.member.Member; import roomescape.member.MemberDao; @@ -15,6 +16,8 @@ public class AdminInterceptor implements HandlerInterceptor { @Autowired private MemberDao memberDao; @Autowired + private JwtService jwtService; + @Autowired private JwtUtil jwtUtil; public AdminInterceptor(JwtUtil jwtUtil) { @@ -33,7 +36,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons return false; } - Long userId = jwtUtil.getUserIdFromToken(token); + Long userId = jwtService.getUserIdFromToken(token); Member member = memberDao.findById(userId); if (member == null || !"ADMIN".equals(member.getRole())) { diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 1742be30..f12d62dc 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -4,7 +4,8 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import roomescape.login.JwtUtil; +import roomescape.jwt.JwtService; +import roomescape.jwt.JwtUtil; import roomescape.member.MemberDao; import roomescape.member.Member; @@ -17,6 +18,8 @@ public class ReservationController { @Autowired private JwtUtil jwtUtil; @Autowired + private JwtService jwtService; + @Autowired private MemberDao memberDao; private final ReservationService reservationService; @@ -39,7 +42,7 @@ public ResponseEntity create(@CookieValue(name = "token", required = true) Strin } if (reservationRequest.getName() == null) { - Long userId = jwtUtil.getUserIdFromToken(token); + Long userId = jwtService.getUserIdFromToken(token); Member member = memberDao.findById(userId); if (member == null) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); From 8b84763c016d84737578bb70f5543bd6482199ca Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 04:31:45 +0900 Subject: [PATCH 13/79] =?UTF-8?q?refactor=20:=20=EC=95=88=20=EC=93=B0?= =?UTF-8?q?=EB=8A=94=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/member/right/AdminInterceptor.java | 4 ---- .../java/roomescape/reservation/ReservationController.java | 2 -- 2 files changed, 6 deletions(-) diff --git a/src/main/java/roomescape/member/right/AdminInterceptor.java b/src/main/java/roomescape/member/right/AdminInterceptor.java index 8dbbfa30..472d5de1 100644 --- a/src/main/java/roomescape/member/right/AdminInterceptor.java +++ b/src/main/java/roomescape/member/right/AdminInterceptor.java @@ -20,10 +20,6 @@ public class AdminInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; - public AdminInterceptor(JwtUtil jwtUtil) { - this.jwtUtil = jwtUtil; - } - @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = null; diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index f12d62dc..153ecaf9 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -15,8 +15,6 @@ @RestController @RequestMapping("/reservations") public class ReservationController { - @Autowired - private JwtUtil jwtUtil; @Autowired private JwtService jwtService; @Autowired From c57fbfb5bd6a9cd9dfc1c9d259be0cce2a636ff7 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 04:52:17 +0900 Subject: [PATCH 14/79] =?UTF-8?q?refactor=20:=20@Autowired=20=EB=8C=80?= =?UTF-8?q?=EC=8B=A0=20=EC=83=9D=EC=84=B1=EC=9E=90=EB=A1=9C=20=EC=A3=BC?= =?UTF-8?q?=EC=9E=85=ED=95=B4=EC=A3=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/jwt/JwtService.java | 6 ++++-- src/main/java/roomescape/jwt/JwtUtil.java | 3 +-- .../java/roomescape/login/LoginController.java | 10 ++++++---- .../java/roomescape/login/LoginRequestDto.java | 2 +- .../java/roomescape/login/LoginService.java | 8 +++++--- .../roomescape/member/MemberController.java | 2 -- .../member/right/AdminInterceptor.java | 11 +++++------ .../reservation/ReservationController.java | 18 ++++++++---------- .../reservation/ReservationRequest.java | 8 ++++---- .../java/roomescape/theme/ThemeController.java | 7 +------ .../java/roomescape/time/TimeController.java | 10 ++-------- 11 files changed, 37 insertions(+), 48 deletions(-) diff --git a/src/main/java/roomescape/jwt/JwtService.java b/src/main/java/roomescape/jwt/JwtService.java index 5d4c9fdd..e3dd37e1 100644 --- a/src/main/java/roomescape/jwt/JwtService.java +++ b/src/main/java/roomescape/jwt/JwtService.java @@ -1,14 +1,16 @@ package roomescape.jwt; import io.jsonwebtoken.Claims; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class JwtService { - @Autowired private JwtUtil jwtUtil; + public JwtService(JwtUtil jwtUtil) { + this.jwtUtil = jwtUtil; + } + public Long getUserIdFromToken(String token) { Claims claims = jwtUtil.getClaimsFromToken(token); try { diff --git a/src/main/java/roomescape/jwt/JwtUtil.java b/src/main/java/roomescape/jwt/JwtUtil.java index 0ed71a26..4ea338be 100644 --- a/src/main/java/roomescape/jwt/JwtUtil.java +++ b/src/main/java/roomescape/jwt/JwtUtil.java @@ -12,11 +12,10 @@ @Component public class JwtUtil { + private static final long EXPIRATION_TIME = 86400000; @Value("${jwt.secret}") private String secretKey; - private static final long EXPIRATION_TIME = 86400000; - private Key generateKey() { return new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName()); } diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index 0445eb34..0613632e 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -2,7 +2,6 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -16,13 +15,16 @@ @RestController @RequestMapping("/login") public class LoginController { - @Autowired private JwtService jwtService; - @Autowired private MemberDao memberDao; - @Autowired private LoginService loginService; + public LoginController(JwtService jwtService, MemberDao memberDao, LoginService loginService) { + this.jwtService = jwtService; + this.memberDao = memberDao; + this.loginService = loginService; + } + @PostMapping public ResponseEntity> login(@RequestBody LoginRequestDto loginRequestDto, HttpServletResponse response) { try { diff --git a/src/main/java/roomescape/login/LoginRequestDto.java b/src/main/java/roomescape/login/LoginRequestDto.java index 97ab4931..e021c2c5 100644 --- a/src/main/java/roomescape/login/LoginRequestDto.java +++ b/src/main/java/roomescape/login/LoginRequestDto.java @@ -4,7 +4,7 @@ public class LoginRequestDto { private String email; private String password; - public LoginRequestDto() {} + //public LoginRequestDto() {} public LoginRequestDto(String email, String password) { this.email = email; diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index c7f6c9f8..92366298 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -1,7 +1,6 @@ package roomescape.login; import jakarta.servlet.http.Cookie; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import roomescape.jwt.JwtUtil; import roomescape.member.Member; @@ -12,11 +11,14 @@ @Service public class LoginService { - @Autowired private JwtUtil jwtUtil; - @Autowired private MemberDao memberDao; + public LoginService(JwtUtil jwtUtil, MemberDao memberDao) { + this.jwtUtil = jwtUtil; + this.memberDao = memberDao; + } + public String authenticate(String email, String password) { Member member = memberDao.findByEmailAndPassword(email, password); if (member == null) { diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index 881ae5e0..fe009d06 100644 --- a/src/main/java/roomescape/member/MemberController.java +++ b/src/main/java/roomescape/member/MemberController.java @@ -1,10 +1,8 @@ package roomescape.member; 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; diff --git a/src/main/java/roomescape/member/right/AdminInterceptor.java b/src/main/java/roomescape/member/right/AdminInterceptor.java index 472d5de1..bd484c63 100644 --- a/src/main/java/roomescape/member/right/AdminInterceptor.java +++ b/src/main/java/roomescape/member/right/AdminInterceptor.java @@ -3,22 +3,21 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import roomescape.jwt.JwtService; -import roomescape.jwt.JwtUtil; import roomescape.member.Member; import roomescape.member.MemberDao; @Component public class AdminInterceptor implements HandlerInterceptor { - @Autowired private MemberDao memberDao; - @Autowired private JwtService jwtService; - @Autowired - private JwtUtil jwtUtil; + + public AdminInterceptor(MemberDao memberDao, JwtService jwtService) { + this.memberDao = memberDao; + this.jwtService = jwtService; + } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 153ecaf9..48ddd12b 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -5,9 +5,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import roomescape.jwt.JwtService; -import roomescape.jwt.JwtUtil; -import roomescape.member.MemberDao; import roomescape.member.Member; +import roomescape.member.MemberDao; import java.net.URI; import java.util.List; @@ -15,13 +14,12 @@ @RestController @RequestMapping("/reservations") public class ReservationController { + private final ReservationService reservationService; @Autowired private JwtService jwtService; @Autowired private MemberDao memberDao; - private final ReservationService reservationService; - public ReservationController(ReservationService reservationService) { this.reservationService = reservationService; } @@ -40,12 +38,12 @@ public ResponseEntity create(@CookieValue(name = "token", required = true) Strin } if (reservationRequest.getName() == null) { - Long userId = jwtService.getUserIdFromToken(token); - Member member = memberDao.findById(userId); - if (member == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - reservationRequest.setName(member.getName()); + Long userId = jwtService.getUserIdFromToken(token); + Member member = memberDao.findById(userId); + if (member == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + reservationRequest.setName(member.getName()); } ReservationResponse reservation = reservationService.save(reservationRequest); diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index a07a8483..a83fb023 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -10,6 +10,10 @@ public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + public String getDate() { return date; } @@ -21,8 +25,4 @@ public Long getTheme() { public Long getTime() { return time; } - - public void setName(String name) { - this.name = name; - } } diff --git a/src/main/java/roomescape/theme/ThemeController.java b/src/main/java/roomescape/theme/ThemeController.java index 03bca41a..7fa46abc 100644 --- a/src/main/java/roomescape/theme/ThemeController.java +++ b/src/main/java/roomescape/theme/ThemeController.java @@ -1,12 +1,7 @@ package roomescape.theme; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.net.URI; import java.util.List; diff --git a/src/main/java/roomescape/time/TimeController.java b/src/main/java/roomescape/time/TimeController.java index 2343114d..aab0df3d 100644 --- a/src/main/java/roomescape/time/TimeController.java +++ b/src/main/java/roomescape/time/TimeController.java @@ -1,13 +1,7 @@ package roomescape.time; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.net.URI; import java.util.List; @@ -45,4 +39,4 @@ public ResponseEntity delete(@PathVariable Long id) { public ResponseEntity> availableTimes(@RequestParam String date, @RequestParam Long themeId) { return ResponseEntity.ok(timeService.getAvailableTime(date, themeId)); } -} \ No newline at end of file +} From 0dbb542f252548ce3036c02919047ee2dc4193a0 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 05:45:25 +0900 Subject: [PATCH 15/79] =?UTF-8?q?refactor=20:=20=EC=BD=94=EB=93=9C=20inden?= =?UTF-8?q?t=20depth=20=EC=A4=84=EC=9D=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/right/AdminInterceptor.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/roomescape/member/right/AdminInterceptor.java b/src/main/java/roomescape/member/right/AdminInterceptor.java index bd484c63..9a1551b5 100644 --- a/src/main/java/roomescape/member/right/AdminInterceptor.java +++ b/src/main/java/roomescape/member/right/AdminInterceptor.java @@ -9,6 +9,8 @@ import roomescape.member.Member; import roomescape.member.MemberDao; +import java.util.Arrays; + @Component public class AdminInterceptor implements HandlerInterceptor { private MemberDao memberDao; @@ -43,13 +45,14 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons } private String extractTokenFromCookies(Cookie[] cookies) { - if (cookies != null) { - for (Cookie cookie : cookies) { - if ("token".equals(cookie.getName())) { - return cookie.getValue(); - } - } + if (cookies == null) { + return null; } - return null; + + return Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .map(Cookie::getValue) + .findFirst() + .orElse(null); } } From 903343eb3372934f8520fd18f2eef1dbd8d87a11 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 06:07:41 +0900 Subject: [PATCH 16/79] =?UTF-8?q?refactor=20:=20boolean=EB=8C=80=EC=8B=A0?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/ExceptionController.java | 8 ++++++++ .../roomescape/member/right/AdminInterceptor.java | 13 +++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/roomescape/ExceptionController.java b/src/main/java/roomescape/ExceptionController.java index 4e2450f9..c10ff4b2 100644 --- a/src/main/java/roomescape/ExceptionController.java +++ b/src/main/java/roomescape/ExceptionController.java @@ -3,12 +3,20 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.server.ResponseStatusException; @ControllerAdvice public class ExceptionController { + + @ExceptionHandler(ResponseStatusException.class) + public ResponseEntity handleResponseStatusException(ResponseStatusException e) { + return ResponseEntity.status(e.getStatusCode()).build(); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleRuntimeException(Exception e) { e.printStackTrace(); return ResponseEntity.badRequest().build(); } } + diff --git a/src/main/java/roomescape/member/right/AdminInterceptor.java b/src/main/java/roomescape/member/right/AdminInterceptor.java index 9a1551b5..60214fd9 100644 --- a/src/main/java/roomescape/member/right/AdminInterceptor.java +++ b/src/main/java/roomescape/member/right/AdminInterceptor.java @@ -3,7 +3,9 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; +import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.HandlerInterceptor; import roomescape.jwt.JwtService; import roomescape.member.Member; @@ -23,22 +25,17 @@ public AdminInterceptor(MemberDao memberDao, JwtService jwtService) { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - String token = null; - - Cookie[] cookies = request.getCookies(); - token = extractTokenFromCookies(cookies); + String token = extractTokenFromCookies(request.getCookies()); if (token == null) { - response.setStatus(401); - return false; + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "토큰을 찾을 수 없습니다."); } Long userId = jwtService.getUserIdFromToken(token); Member member = memberDao.findById(userId); if (member == null || !"ADMIN".equals(member.getRole())) { - response.setStatus(401); - return false; + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "사용자를 찾을 수 없습니다."); } return true; From fa6d70c03cb72d08c7a55994550fc2e7765c1412 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 06:34:38 +0900 Subject: [PATCH 17/79] =?UTF-8?q?refactor=20:=20try-catch=EB=A5=BC=20Excep?= =?UTF-8?q?tionHandler=EB=A1=9C=20=EC=B2=98=EB=A6=AC=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/ExceptionController.java | 11 +++++ .../roomescape/login/LoginController.java | 40 ++++++------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/main/java/roomescape/ExceptionController.java b/src/main/java/roomescape/ExceptionController.java index c10ff4b2..e452ff0c 100644 --- a/src/main/java/roomescape/ExceptionController.java +++ b/src/main/java/roomescape/ExceptionController.java @@ -1,10 +1,14 @@ package roomescape; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.server.ResponseStatusException; +import java.util.HashMap; +import java.util.Map; + @ControllerAdvice public class ExceptionController { @@ -13,6 +17,13 @@ public ResponseEntity handleResponseStatusException(ResponseStatusExceptio return ResponseEntity.status(e.getStatusCode()).build(); } + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity> handleIllegalArgumentException(IllegalArgumentException e) { + Map errorResponse = new HashMap<>(); + errorResponse.put("message", e.getMessage()); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleRuntimeException(Exception e) { e.printStackTrace(); diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index 0613632e..fb5b8c50 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -2,7 +2,6 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import roomescape.jwt.JwtService; @@ -27,37 +26,24 @@ public LoginController(JwtService jwtService, MemberDao memberDao, LoginService @PostMapping public ResponseEntity> login(@RequestBody LoginRequestDto loginRequestDto, HttpServletResponse response) { - try { - String token = loginService.authenticate(loginRequestDto.getEmail(), loginRequestDto.getPassword()); - - Cookie cookie = loginService.createAuthCookie(token); - response.addCookie(cookie); - Map responseBody = loginService.createLoginResponse(token); - - return ResponseEntity.ok(responseBody); - } catch (IllegalArgumentException e) { - Map errorResponse = new HashMap<>(); - errorResponse.put("message", e.getMessage()); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); - } + String token = loginService.authenticate(loginRequestDto.getEmail(), loginRequestDto.getPassword()); + Cookie cookie = loginService.createAuthCookie(token); + response.addCookie(cookie); + Map responseBody = loginService.createLoginResponse(token); + return ResponseEntity.ok(responseBody); } @GetMapping("/check") public ResponseEntity> checkLogin(@CookieValue(name = "token", required = true) String token) { - try { - Long userId = jwtService.getUserIdFromToken(token); - Member member = memberDao.findById(userId); - - if (member == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } + Long userId = jwtService.getUserIdFromToken(token); + Member member = memberDao.findById(userId); - Map response = new HashMap<>(); - response.put("name", member.getName()); - - return ResponseEntity.ok(response); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + if (member == null) { + throw new IllegalArgumentException("유효하지 않은 사용자입니다."); } + + Map response = new HashMap<>(); + response.put("name", member.getName()); + return ResponseEntity.ok(response); } } From 787dd0334f540d4f76d81925df8b31cee3b7afdd Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 08:34:09 +0900 Subject: [PATCH 18/79] =?UTF-8?q?refactor=20:=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../right => auth}/AdminInterceptor.java | 18 +++---- .../java/roomescape/auth/Authentication.java | 9 ++++ .../auth/AuthenticationArgumentResolver.java | 52 +++++++++++++++++++ .../{member/right => auth}/WebConfig.java | 15 +++++- src/main/java/roomescape/jwt/JwtService.java | 18 +++++-- .../reservation/ReservationController.java | 25 ++------- src/test/java/roomescape/MissionStepTest.java | 2 +- 7 files changed, 99 insertions(+), 40 deletions(-) rename src/main/java/roomescape/{member/right => auth}/AdminInterceptor.java (73%) create mode 100644 src/main/java/roomescape/auth/Authentication.java create mode 100644 src/main/java/roomescape/auth/AuthenticationArgumentResolver.java rename src/main/java/roomescape/{member/right => auth}/WebConfig.java (50%) diff --git a/src/main/java/roomescape/member/right/AdminInterceptor.java b/src/main/java/roomescape/auth/AdminInterceptor.java similarity index 73% rename from src/main/java/roomescape/member/right/AdminInterceptor.java rename to src/main/java/roomescape/auth/AdminInterceptor.java index 60214fd9..9edfe6ff 100644 --- a/src/main/java/roomescape/member/right/AdminInterceptor.java +++ b/src/main/java/roomescape/auth/AdminInterceptor.java @@ -1,4 +1,4 @@ -package roomescape.member.right; +package roomescape.auth; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; @@ -9,32 +9,26 @@ import org.springframework.web.servlet.HandlerInterceptor; import roomescape.jwt.JwtService; import roomescape.member.Member; -import roomescape.member.MemberDao; import java.util.Arrays; @Component public class AdminInterceptor implements HandlerInterceptor { - private MemberDao memberDao; - private JwtService jwtService; + private final JwtService jwtService; - public AdminInterceptor(MemberDao memberDao, JwtService jwtService) { - this.memberDao = memberDao; + public AdminInterceptor(JwtService jwtService) { this.jwtService = jwtService; } @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token = extractTokenFromCookies(request.getCookies()); - if (token == null) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "토큰을 찾을 수 없습니다."); } - Long userId = jwtService.getUserIdFromToken(token); - Member member = memberDao.findById(userId); - - if (member == null || !"ADMIN".equals(member.getRole())) { + Member member = jwtService.getMemberFromToken(token); + if (!"ADMIN".equals(member.getRole())) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "사용자를 찾을 수 없습니다."); } diff --git a/src/main/java/roomescape/auth/Authentication.java b/src/main/java/roomescape/auth/Authentication.java new file mode 100644 index 00000000..d68d8fe3 --- /dev/null +++ b/src/main/java/roomescape/auth/Authentication.java @@ -0,0 +1,9 @@ +package roomescape.auth; + +import java.lang.annotation.*; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Authentication { +} diff --git a/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java b/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java new file mode 100644 index 00000000..0d3ef1d9 --- /dev/null +++ b/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java @@ -0,0 +1,52 @@ +package roomescape.auth; + +import org.springframework.beans.factory.annotation.Autowired; +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 roomescape.jwt.JwtService; +import roomescape.member.Member; + +import java.util.Arrays; +import java.util.Optional; + +@Component +public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver { + + @Autowired + private JwtService jwtService; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(Authentication.class) + && parameter.getParameterType().equals(Member.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) { + + String token = extractTokenFromCookies(webRequest) + .orElseThrow(() -> new IllegalArgumentException("토큰이 존재하지 않습니다. 로그인이 필요합니다.")); + + return jwtService.getMemberFromToken(token); + } + + private Optional extractTokenFromCookies(NativeWebRequest webRequest) { + String cookieHeader = webRequest.getHeader("Cookie"); + if (cookieHeader == null) { + return Optional.empty(); + } + + return Arrays.stream(cookieHeader.split(";")) + .map(String::trim) + .filter(cookie -> cookie.startsWith("token=")) + .map(cookie -> cookie.substring("token=".length())) + .findFirst(); + } +} diff --git a/src/main/java/roomescape/member/right/WebConfig.java b/src/main/java/roomescape/auth/WebConfig.java similarity index 50% rename from src/main/java/roomescape/member/right/WebConfig.java rename to src/main/java/roomescape/auth/WebConfig.java index 892ca173..ffe6b316 100644 --- a/src/main/java/roomescape/member/right/WebConfig.java +++ b/src/main/java/roomescape/auth/WebConfig.java @@ -1,16 +1,21 @@ -package roomescape.member.right; +package roomescape.auth; 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; + @Configuration public class WebConfig implements WebMvcConfigurer { private final AdminInterceptor adminInterceptor; + private final AuthenticationArgumentResolver authenticationArgumentResolver; - public WebConfig(AdminInterceptor adminInterceptor) { + public WebConfig(AdminInterceptor adminInterceptor, AuthenticationArgumentResolver authenticationArgumentResolver) { this.adminInterceptor = adminInterceptor; + this.authenticationArgumentResolver = authenticationArgumentResolver; } @Override @@ -18,4 +23,10 @@ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(adminInterceptor) .addPathPatterns("/admin"); } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(authenticationArgumentResolver); + } } + diff --git a/src/main/java/roomescape/jwt/JwtService.java b/src/main/java/roomescape/jwt/JwtService.java index e3dd37e1..6168eeae 100644 --- a/src/main/java/roomescape/jwt/JwtService.java +++ b/src/main/java/roomescape/jwt/JwtService.java @@ -2,13 +2,17 @@ import io.jsonwebtoken.Claims; import org.springframework.stereotype.Service; +import roomescape.member.Member; +import roomescape.member.MemberDao; @Service public class JwtService { - private JwtUtil jwtUtil; + private final JwtUtil jwtUtil; + private final MemberDao memberDao; - public JwtService(JwtUtil jwtUtil) { + public JwtService(JwtUtil jwtUtil, MemberDao memberDao) { this.jwtUtil = jwtUtil; + this.memberDao = memberDao; } public Long getUserIdFromToken(String token) { @@ -19,5 +23,13 @@ public Long getUserIdFromToken(String token) { throw new IllegalArgumentException("Claims에서 User ID를 추출할 수 없습니다.", e); } } -} + public Member getMemberFromToken(String token) { + Long userId = getUserIdFromToken(token); + Member member = memberDao.findById(userId); + if (member == null) { + throw new IllegalArgumentException("토큰으로부터 유저를 찾을 수 없습니다."); + } + return member; + } +} diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 48ddd12b..a5bff447 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -1,12 +1,9 @@ package roomescape.reservation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import roomescape.jwt.JwtService; +import roomescape.auth.Authentication; import roomescape.member.Member; -import roomescape.member.MemberDao; import java.net.URI; import java.util.List; @@ -15,10 +12,6 @@ @RequestMapping("/reservations") public class ReservationController { private final ReservationService reservationService; - @Autowired - private JwtService jwtService; - @Autowired - private MemberDao memberDao; public ReservationController(ReservationService reservationService) { this.reservationService = reservationService; @@ -30,27 +23,15 @@ public List list() { } @PostMapping - public ResponseEntity create(@CookieValue(name = "token", required = true) String token, @RequestBody ReservationRequest reservationRequest) { - if (reservationRequest.getDate() == null - || reservationRequest.getTheme() == null - || reservationRequest.getTime() == null) { - return ResponseEntity.badRequest().build(); - } - + public ResponseEntity create(@Authentication Member member, + @RequestBody ReservationRequest reservationRequest) { if (reservationRequest.getName() == null) { - Long userId = jwtService.getUserIdFromToken(token); - Member member = memberDao.findById(userId); - if (member == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } reservationRequest.setName(member.getName()); } - ReservationResponse reservation = reservationService.save(reservationRequest); return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); } - @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable Long id) { reservationService.deleteById(id); diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 353db353..57d71965 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -63,7 +63,7 @@ private String createToken(String email, String password) { @Test void 이단계() { - String token = createToken("admin@email.com", "password"); // 일단계에서 토큰을 추출하는 로직을 메서드로 따로 만들어서 활용하세요. + String token = createToken("admin@email.com", "password"); Map params = new HashMap<>(); params.put("date", "2024-03-01"); From 6591dba63373c7070ee354ed42df2a92883eff97 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 08:37:11 +0900 Subject: [PATCH 19/79] =?UTF-8?q?refactor=20:=20loginController=EC=9D=98?= =?UTF-8?q?=20=EB=A9=A4=EB=B2=84=20=EC=B0=BE=EB=8A=94=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20service=EA=B3=84=EC=B8=B5=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=98=AE=EA=B8=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/login/LoginController.java | 7 +------ src/main/java/roomescape/login/LoginService.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index fb5b8c50..fe28b201 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -35,12 +35,7 @@ public ResponseEntity> login(@RequestBody LoginRequestDto lo @GetMapping("/check") public ResponseEntity> checkLogin(@CookieValue(name = "token", required = true) String token) { - Long userId = jwtService.getUserIdFromToken(token); - Member member = memberDao.findById(userId); - - if (member == null) { - throw new IllegalArgumentException("유효하지 않은 사용자입니다."); - } + Member member = loginService.validateUserFromToken(token); Map response = new HashMap<>(); response.put("name", member.getName()); diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index 92366298..9e508584 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -2,6 +2,7 @@ import jakarta.servlet.http.Cookie; import org.springframework.stereotype.Service; +import roomescape.jwt.JwtService; import roomescape.jwt.JwtUtil; import roomescape.member.Member; import roomescape.member.MemberDao; @@ -12,10 +13,12 @@ @Service public class LoginService { private JwtUtil jwtUtil; + private JwtService jwtService; private MemberDao memberDao; - public LoginService(JwtUtil jwtUtil, MemberDao memberDao) { + public LoginService(JwtUtil jwtUtil, JwtService jwtService, MemberDao memberDao) { this.jwtUtil = jwtUtil; + this.jwtService = jwtService; this.memberDao = memberDao; } @@ -42,4 +45,15 @@ public Map createLoginResponse(String token) { responseBody.put("message", "Login successful"); return responseBody; } + + public Member validateUserFromToken(String token) { + Long userId = jwtService.getUserIdFromToken(token); + Member member = memberDao.findById(userId); + + if (member == null) { + throw new IllegalArgumentException("유효하지 않은 사용자입니다."); + } + + return member; + } } From d1d0e04aad87c8c82456b75dbcc692169e52125e Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 08:48:49 +0900 Subject: [PATCH 20/79] =?UTF-8?q?refactor=20:=20LoginController=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=EC=97=86=EB=8A=94=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=9C=EA=B1=B0=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/login/LoginController.java | 6 +----- src/main/java/roomescape/login/LoginRequestDto.java | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index fe28b201..b039769a 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -14,13 +14,9 @@ @RestController @RequestMapping("/login") public class LoginController { - private JwtService jwtService; - private MemberDao memberDao; private LoginService loginService; - public LoginController(JwtService jwtService, MemberDao memberDao, LoginService loginService) { - this.jwtService = jwtService; - this.memberDao = memberDao; + public LoginController(LoginService loginService) { this.loginService = loginService; } diff --git a/src/main/java/roomescape/login/LoginRequestDto.java b/src/main/java/roomescape/login/LoginRequestDto.java index e021c2c5..0f30e886 100644 --- a/src/main/java/roomescape/login/LoginRequestDto.java +++ b/src/main/java/roomescape/login/LoginRequestDto.java @@ -4,8 +4,6 @@ public class LoginRequestDto { private String email; private String password; - //public LoginRequestDto() {} - public LoginRequestDto(String email, String password) { this.email = email; this.password = password; From 7abea53530858df1013e0d90cc1ce5e177a5758c Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 08:59:47 +0900 Subject: [PATCH 21/79] =?UTF-8?q?refactor=20:=20=EB=A9=A4=EB=B2=84?= =?UTF-8?q?=EC=B0=BE=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/AuthenticationArgumentResolver.java | 19 ++--------- .../roomescape/login/LoginController.java | 6 ++-- .../java/roomescape/login/LoginService.java | 23 +++---------- src/main/java/roomescape/util/CookieUtil.java | 32 +++++++++++++++++++ 4 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 src/main/java/roomescape/util/CookieUtil.java diff --git a/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java b/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java index 0d3ef1d9..16899699 100644 --- a/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java +++ b/src/main/java/roomescape/auth/AuthenticationArgumentResolver.java @@ -9,9 +9,7 @@ import org.springframework.web.method.support.ModelAndViewContainer; import roomescape.jwt.JwtService; import roomescape.member.Member; - -import java.util.Arrays; -import java.util.Optional; +import roomescape.util.CookieUtil; @Component public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver { @@ -31,22 +29,9 @@ public Object resolveArgument(MethodParameter parameter, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { - String token = extractTokenFromCookies(webRequest) + String token = CookieUtil.extractTokenFromHeader(webRequest) .orElseThrow(() -> new IllegalArgumentException("토큰이 존재하지 않습니다. 로그인이 필요합니다.")); return jwtService.getMemberFromToken(token); } - - private Optional extractTokenFromCookies(NativeWebRequest webRequest) { - String cookieHeader = webRequest.getHeader("Cookie"); - if (cookieHeader == null) { - return Optional.empty(); - } - - return Arrays.stream(cookieHeader.split(";")) - .map(String::trim) - .filter(cookie -> cookie.startsWith("token=")) - .map(cookie -> cookie.substring("token=".length())) - .findFirst(); - } } diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index b039769a..8e155754 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -15,9 +15,11 @@ @RequestMapping("/login") public class LoginController { private LoginService loginService; + private JwtService jwtService; - public LoginController(LoginService loginService) { + public LoginController(LoginService loginService, JwtService jwtService) { this.loginService = loginService; + this.jwtService = jwtService; } @PostMapping @@ -31,7 +33,7 @@ public ResponseEntity> login(@RequestBody LoginRequestDto lo @GetMapping("/check") public ResponseEntity> checkLogin(@CookieValue(name = "token", required = true) String token) { - Member member = loginService.validateUserFromToken(token); + Member member = jwtService.getMemberFromToken(token); Map response = new HashMap<>(); response.put("name", member.getName()); diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index 9e508584..02fd604c 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -2,7 +2,6 @@ import jakarta.servlet.http.Cookie; import org.springframework.stereotype.Service; -import roomescape.jwt.JwtService; import roomescape.jwt.JwtUtil; import roomescape.member.Member; import roomescape.member.MemberDao; @@ -12,13 +11,11 @@ @Service public class LoginService { - private JwtUtil jwtUtil; - private JwtService jwtService; - private MemberDao memberDao; + private final JwtUtil jwtUtil; + private final MemberDao memberDao; - public LoginService(JwtUtil jwtUtil, JwtService jwtService, MemberDao memberDao) { + public LoginService(JwtUtil jwtUtil, MemberDao memberDao) { this.jwtUtil = jwtUtil; - this.jwtService = jwtService; this.memberDao = memberDao; } @@ -28,8 +25,7 @@ public String authenticate(String email, String password) { throw new IllegalArgumentException("Invalid email or password"); } - String role = member.getRole(); - return jwtUtil.generateToken(member.getId(), role); + return jwtUtil.generateToken(member.getId(), member.getRole()); } public Cookie createAuthCookie(String token) { @@ -45,15 +41,4 @@ public Map createLoginResponse(String token) { responseBody.put("message", "Login successful"); return responseBody; } - - public Member validateUserFromToken(String token) { - Long userId = jwtService.getUserIdFromToken(token); - Member member = memberDao.findById(userId); - - if (member == null) { - throw new IllegalArgumentException("유효하지 않은 사용자입니다."); - } - - return member; - } } diff --git a/src/main/java/roomescape/util/CookieUtil.java b/src/main/java/roomescape/util/CookieUtil.java new file mode 100644 index 00000000..e29618cd --- /dev/null +++ b/src/main/java/roomescape/util/CookieUtil.java @@ -0,0 +1,32 @@ +package roomescape.util; + +import jakarta.servlet.http.Cookie; +import org.springframework.web.context.request.NativeWebRequest; + +import java.util.Arrays; +import java.util.Optional; + +public class CookieUtil { + + public static Optional extractTokenFromCookies(Cookie[] cookies) { + if (cookies == null) { + return Optional.empty(); + } + return Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .map(Cookie::getValue) + .findFirst(); + } + + public static Optional extractTokenFromHeader(NativeWebRequest webRequest) { + String cookieHeader = webRequest.getHeader("Cookie"); + if (cookieHeader == null) { + return Optional.empty(); + } + return Arrays.stream(cookieHeader.split(";")) + .map(String::trim) + .filter(cookie -> cookie.startsWith("token=")) + .map(cookie -> cookie.substring("token=".length())) + .findFirst(); + } +} From 2ce4d0d6003d769633940547057c4bb5ce7fa785 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 12:24:21 +0900 Subject: [PATCH 22/79] =?UTF-8?q?feat=20:=20gradle=EC=97=90=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 8d52aebc..00e45f2f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'dev.akkinoc.spring.boot:logback-access-spring-boot-starter:4.0.0' @@ -26,6 +27,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.rest-assured:rest-assured:5.3.1' + implementation 'com.h2database:h2' runtimeOnly 'com.h2database:h2' } From 62ebd1c80c747fa64ee73ae2bebbee905d19af35 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 12:52:33 +0900 Subject: [PATCH 23/79] =?UTF-8?q?feat=20:=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/member/Member.java | 12 ++++++++++ .../roomescape/member/MemberController.java | 2 ++ .../roomescape/member/MemberRepository.java | 6 +++++ .../java/roomescape/member/MemberService.java | 2 ++ .../member/{ => dto}/MemberRequest.java | 2 +- .../member/{ => dto}/MemberResponse.java | 2 +- .../roomescape/reservation/Reservation.java | 12 ++++++++++ .../reservation/ReservationController.java | 2 ++ .../reservation/ReservationDao.java | 1 + .../reservation/ReservationRepository.java | 7 ++++++ .../reservation/ReservationService.java | 2 ++ .../{ => dto}/ReservationRequest.java | 2 +- .../{ => dto}/ReservationResponse.java | 2 +- src/main/java/roomescape/theme/Theme.java | 9 ++++++++ .../roomescape/theme/ThemeRepository.java | 6 +++++ src/main/java/roomescape/time/Time.java | 16 +++++++++---- .../java/roomescape/time/TimeRepository.java | 6 +++++ src/main/resources/application.properties | 10 ++++---- src/test/java/roomescape/MissionStepTest.java | 23 ++++++++++++++++++- 19 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 src/main/java/roomescape/member/MemberRepository.java rename src/main/java/roomescape/member/{ => dto}/MemberRequest.java (90%) rename src/main/java/roomescape/member/{ => dto}/MemberResponse.java (93%) create mode 100644 src/main/java/roomescape/reservation/ReservationRepository.java rename src/main/java/roomescape/reservation/{ => dto}/ReservationRequest.java (92%) rename src/main/java/roomescape/reservation/{ => dto}/ReservationResponse.java (94%) create mode 100644 src/main/java/roomescape/theme/ThemeRepository.java create mode 100644 src/main/java/roomescape/time/TimeRepository.java diff --git a/src/main/java/roomescape/member/Member.java b/src/main/java/roomescape/member/Member.java index 903aaa9b..a8fdd66f 100644 --- a/src/main/java/roomescape/member/Member.java +++ b/src/main/java/roomescape/member/Member.java @@ -1,12 +1,24 @@ package roomescape.member; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity public class Member { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; private String email; private String password; private String role; + public Member() { + } + public Member(Long id, String name, String email, String role) { this.id = id; this.name = name; diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index fe009d06..32c83cb6 100644 --- a/src/main/java/roomescape/member/MemberController.java +++ b/src/main/java/roomescape/member/MemberController.java @@ -6,6 +6,8 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import roomescape.member.dto.MemberRequest; +import roomescape.member.dto.MemberResponse; import java.net.URI; diff --git a/src/main/java/roomescape/member/MemberRepository.java b/src/main/java/roomescape/member/MemberRepository.java new file mode 100644 index 00000000..c5cb5414 --- /dev/null +++ b/src/main/java/roomescape/member/MemberRepository.java @@ -0,0 +1,6 @@ +package roomescape.member; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { +} diff --git a/src/main/java/roomescape/member/MemberService.java b/src/main/java/roomescape/member/MemberService.java index ccaa8cba..a1cb1e98 100644 --- a/src/main/java/roomescape/member/MemberService.java +++ b/src/main/java/roomescape/member/MemberService.java @@ -1,6 +1,8 @@ package roomescape.member; import org.springframework.stereotype.Service; +import roomescape.member.dto.MemberRequest; +import roomescape.member.dto.MemberResponse; @Service public class MemberService { diff --git a/src/main/java/roomescape/member/MemberRequest.java b/src/main/java/roomescape/member/dto/MemberRequest.java similarity index 90% rename from src/main/java/roomescape/member/MemberRequest.java rename to src/main/java/roomescape/member/dto/MemberRequest.java index cafb79f1..7f7b0fb6 100644 --- a/src/main/java/roomescape/member/MemberRequest.java +++ b/src/main/java/roomescape/member/dto/MemberRequest.java @@ -1,4 +1,4 @@ -package roomescape.member; +package roomescape.member.dto; public class MemberRequest { private String name; diff --git a/src/main/java/roomescape/member/MemberResponse.java b/src/main/java/roomescape/member/dto/MemberResponse.java similarity index 93% rename from src/main/java/roomescape/member/MemberResponse.java rename to src/main/java/roomescape/member/dto/MemberResponse.java index b9fa3b97..b3235d2c 100644 --- a/src/main/java/roomescape/member/MemberResponse.java +++ b/src/main/java/roomescape/member/dto/MemberResponse.java @@ -1,4 +1,4 @@ -package roomescape.member; +package roomescape.member.dto; public class MemberResponse { private Long id; diff --git a/src/main/java/roomescape/reservation/Reservation.java b/src/main/java/roomescape/reservation/Reservation.java index 83a7edf1..1a10d4a1 100644 --- a/src/main/java/roomescape/reservation/Reservation.java +++ b/src/main/java/roomescape/reservation/Reservation.java @@ -1,13 +1,25 @@ package roomescape.reservation; +import jakarta.persistence.*; import roomescape.theme.Theme; import roomescape.time.Time; + +@Entity public class Reservation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; private String date; + + @ManyToOne(fetch = FetchType.LAZY) // Time 엔티티와 다대일 관계 + @JoinColumn(name = "time_id", nullable = false) // 외래 키 매핑 private Time time; + + @ManyToOne(fetch = FetchType.LAZY) // Theme 엔티티와 다대일 관계 + @JoinColumn(name = "theme_id", nullable = false) // 외래 키 매핑 private Theme theme; public Reservation(Long id, String name, String date, Time time, Theme theme) { diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index a5bff447..99bcb422 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -4,6 +4,8 @@ import org.springframework.web.bind.annotation.*; import roomescape.auth.Authentication; import roomescape.member.Member; +import roomescape.reservation.dto.ReservationRequest; +import roomescape.reservation.dto.ReservationResponse; import java.net.URI; import java.util.List; diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java index a4972430..80b03fd4 100644 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ b/src/main/java/roomescape/reservation/ReservationDao.java @@ -4,6 +4,7 @@ import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Repository; +import roomescape.reservation.dto.ReservationRequest; import roomescape.theme.Theme; import roomescape.time.Time; diff --git a/src/main/java/roomescape/reservation/ReservationRepository.java b/src/main/java/roomescape/reservation/ReservationRepository.java new file mode 100644 index 00000000..8fd3110d --- /dev/null +++ b/src/main/java/roomescape/reservation/ReservationRepository.java @@ -0,0 +1,7 @@ +package roomescape.reservation; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReservationRepository extends JpaRepository { +} + diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index bd331332..b14a22d5 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -1,6 +1,8 @@ package roomescape.reservation; import org.springframework.stereotype.Service; +import roomescape.reservation.dto.ReservationRequest; +import roomescape.reservation.dto.ReservationResponse; import java.util.List; diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/dto/ReservationRequest.java similarity index 92% rename from src/main/java/roomescape/reservation/ReservationRequest.java rename to src/main/java/roomescape/reservation/dto/ReservationRequest.java index a83fb023..39d1cd83 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/dto/ReservationRequest.java @@ -1,4 +1,4 @@ -package roomescape.reservation; +package roomescape.reservation.dto; public class ReservationRequest { private String name; diff --git a/src/main/java/roomescape/reservation/ReservationResponse.java b/src/main/java/roomescape/reservation/dto/ReservationResponse.java similarity index 94% rename from src/main/java/roomescape/reservation/ReservationResponse.java rename to src/main/java/roomescape/reservation/dto/ReservationResponse.java index 41360a36..2c219d01 100644 --- a/src/main/java/roomescape/reservation/ReservationResponse.java +++ b/src/main/java/roomescape/reservation/dto/ReservationResponse.java @@ -1,4 +1,4 @@ -package roomescape.reservation; +package roomescape.reservation.dto; public class ReservationResponse { private Long id; diff --git a/src/main/java/roomescape/theme/Theme.java b/src/main/java/roomescape/theme/Theme.java index 430a6239..0805464d 100644 --- a/src/main/java/roomescape/theme/Theme.java +++ b/src/main/java/roomescape/theme/Theme.java @@ -1,7 +1,16 @@ package roomescape.theme; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity public class Theme { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; private String description; diff --git a/src/main/java/roomescape/theme/ThemeRepository.java b/src/main/java/roomescape/theme/ThemeRepository.java new file mode 100644 index 00000000..cbdb21a3 --- /dev/null +++ b/src/main/java/roomescape/theme/ThemeRepository.java @@ -0,0 +1,6 @@ +package roomescape.theme; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ThemeRepository extends JpaRepository { +} diff --git a/src/main/java/roomescape/time/Time.java b/src/main/java/roomescape/time/Time.java index 008ed93c..bc5a8f99 100644 --- a/src/main/java/roomescape/time/Time.java +++ b/src/main/java/roomescape/time/Time.java @@ -1,9 +1,21 @@ package roomescape.time; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity public class Time { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String value; + public Time() { + } + public Time(Long id, String value) { this.id = id; this.value = value; @@ -13,10 +25,6 @@ public Time(String value) { this.value = value; } - public Time() { - - } - public Long getId() { return id; } diff --git a/src/main/java/roomescape/time/TimeRepository.java b/src/main/java/roomescape/time/TimeRepository.java new file mode 100644 index 00000000..99810064 --- /dev/null +++ b/src/main/java/roomescape/time/TimeRepository.java @@ -0,0 +1,6 @@ +package roomescape.time; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TimeRepository extends JpaRepository { +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b7e470c4..32c9618c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,9 +4,7 @@ spring.h2.console.path=/h2-console spring.datasource.url=jdbc:h2:mem:database jwt.secret=${JWT_SECRET_KEY} -#spring.jpa.show-sql=true -#spring.jpa.properties.hibernate.format_sql=true -#spring.jpa.ddl-auto=create-drop -#spring.jpa.defer-datasource-initialization=true - -#roomescape.auth.jwt.secret= Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E= +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.ddl-auto=create-drop +spring.jpa.defer-datasource-initialization=true diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 57d71965..d6c373aa 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -5,9 +5,13 @@ 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.autoconfigure.orm.jpa.TestEntityManager; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; -import roomescape.reservation.ReservationResponse; +import roomescape.reservation.dto.ReservationResponse; +import roomescape.time.Time; +import roomescape.time.TimeRepository; import java.util.HashMap; import java.util.Map; @@ -113,4 +117,21 @@ private String createToken(String email, String password) { .then().log().all() .statusCode(200); } + + @Autowired + private TestEntityManager entityManager; + + @Autowired + private TimeRepository timeRepository; + + @Test + void 사단계() { + Time time = new Time("10:00"); + entityManager.persist(time); + entityManager.flush(); + + Time persistTime = timeRepository.findById(time.getId()).orElse(null); + + //assertThat(persistTime.getTime()).isEqualTo(time.getTime()); + } } From c4707f955eedf78f89c85def04a1a2d0873c05df Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 13:17:40 +0900 Subject: [PATCH 24/79] =?UTF-8?q?feat=20:=20test=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/roomescape/JpaTest.java | 30 +++++++++++++++++++ src/test/java/roomescape/MissionStepTest.java | 17 ----------- 2 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 src/test/java/roomescape/JpaTest.java diff --git a/src/test/java/roomescape/JpaTest.java b/src/test/java/roomescape/JpaTest.java new file mode 100644 index 00000000..5a49b771 --- /dev/null +++ b/src/test/java/roomescape/JpaTest.java @@ -0,0 +1,30 @@ +package roomescape; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import roomescape.time.Time; +import roomescape.time.TimeRepository; + +import static org.assertj.core.api.FactoryBasedNavigableListAssert.assertThat; + +@DataJpaTest +public class JpaTest { + @Autowired + private TestEntityManager entityManager; + + @Autowired + private TimeRepository timeRepository; + + @Test + void 사단계() { + Time time = new Time("10:00"); + entityManager.persist(time); + entityManager.flush(); + + Time persistTime = timeRepository.findById(time.getId()).orElse(null); + + //assertThat(persistTime.getTime()).isEqualTo(time.getTime()); + } +} diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index d6c373aa..395e955a 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -117,21 +117,4 @@ private String createToken(String email, String password) { .then().log().all() .statusCode(200); } - - @Autowired - private TestEntityManager entityManager; - - @Autowired - private TimeRepository timeRepository; - - @Test - void 사단계() { - Time time = new Time("10:00"); - entityManager.persist(time); - entityManager.flush(); - - Time persistTime = timeRepository.findById(time.getId()).orElse(null); - - //assertThat(persistTime.getTime()).isEqualTo(time.getTime()); - } } From 41881e7c7a38958c68af05b70eb5fd73fcebe0cf Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 13:18:05 +0900 Subject: [PATCH 25/79] =?UTF-8?q?feat=20:=20@repository=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/member/MemberRepository.java | 9 ++++++++- .../roomescape/reservation/ReservationRepository.java | 11 +++++++++++ src/main/java/roomescape/theme/ThemeRepository.java | 2 ++ src/main/java/roomescape/time/TimeRepository.java | 2 ++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/roomescape/member/MemberRepository.java b/src/main/java/roomescape/member/MemberRepository.java index c5cb5414..5e5f770e 100644 --- a/src/main/java/roomescape/member/MemberRepository.java +++ b/src/main/java/roomescape/member/MemberRepository.java @@ -1,6 +1,13 @@ package roomescape.member; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; -public interface MemberRepository extends JpaRepository { +import java.util.Optional; + +@Repository +public interface MemberRepository extends JpaRepository { + Optional findByEmailAndPassword(String email, String password); + + Optional findByName(String name); } diff --git a/src/main/java/roomescape/reservation/ReservationRepository.java b/src/main/java/roomescape/reservation/ReservationRepository.java index 8fd3110d..cbd31be1 100644 --- a/src/main/java/roomescape/reservation/ReservationRepository.java +++ b/src/main/java/roomescape/reservation/ReservationRepository.java @@ -1,7 +1,18 @@ package roomescape.reservation; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import java.util.List; + +@Repository public interface ReservationRepository extends JpaRepository { + + @Query("SELECT r FROM Reservation r JOIN FETCH r.theme t JOIN FETCH r.time ti") + List findAllWithDetails(); + + @Query("SELECT r FROM Reservation r JOIN FETCH r.theme t JOIN FETCH r.time ti WHERE r.date = :date AND r.theme.id = :themeId") + List findByDateAndThemeId(String date, Long themeId); } diff --git a/src/main/java/roomescape/theme/ThemeRepository.java b/src/main/java/roomescape/theme/ThemeRepository.java index cbdb21a3..304cb0ef 100644 --- a/src/main/java/roomescape/theme/ThemeRepository.java +++ b/src/main/java/roomescape/theme/ThemeRepository.java @@ -1,6 +1,8 @@ package roomescape.theme; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface ThemeRepository extends JpaRepository { } diff --git a/src/main/java/roomescape/time/TimeRepository.java b/src/main/java/roomescape/time/TimeRepository.java index 99810064..a6786858 100644 --- a/src/main/java/roomescape/time/TimeRepository.java +++ b/src/main/java/roomescape/time/TimeRepository.java @@ -1,6 +1,8 @@ package roomescape.time; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface TimeRepository extends JpaRepository { } From 8e8c37b4b86db1201d5c8168fe99315666625415 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 13:20:50 +0900 Subject: [PATCH 26/79] =?UTF-8?q?feat=20:=20memberRepository=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/member/MemberDao.java | 138 +++++++++--------- .../java/roomescape/member/MemberService.java | 8 +- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java index 80d2bd30..f328ac03 100644 --- a/src/main/java/roomescape/member/MemberDao.java +++ b/src/main/java/roomescape/member/MemberDao.java @@ -1,69 +1,69 @@ -package roomescape.member; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; - -@Repository -public class MemberDao { - private 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); - - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); - } - - 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 - ); - } - - 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 findById(Long id) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE id = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - rs.getString("role") - ), - id - ); - } - -} +//package roomescape.member; +// +//import org.springframework.jdbc.core.JdbcTemplate; +//import org.springframework.jdbc.support.GeneratedKeyHolder; +//import org.springframework.jdbc.support.KeyHolder; +//import org.springframework.stereotype.Repository; +// +//@Repository +//public class MemberDao { +// private 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); +// +// return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); +// } +// +// 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 +// ); +// } +// +// 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 findById(Long id) { +// return jdbcTemplate.queryForObject( +// "SELECT id, name, email, role FROM member WHERE id = ?", +// (rs, rowNum) -> new Member( +// rs.getLong("id"), +// rs.getString("name"), +// rs.getString("email"), +// rs.getString("role") +// ), +// id +// ); +// } +// +//} diff --git a/src/main/java/roomescape/member/MemberService.java b/src/main/java/roomescape/member/MemberService.java index a1cb1e98..39d1c754 100644 --- a/src/main/java/roomescape/member/MemberService.java +++ b/src/main/java/roomescape/member/MemberService.java @@ -6,14 +6,14 @@ @Service public class MemberService { - private MemberDao memberDao; + private final MemberRepository memberRepository; - public MemberService(MemberDao memberDao) { - this.memberDao = memberDao; + public MemberService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; } public MemberResponse createMember(MemberRequest memberRequest) { - Member member = memberDao.save(new Member(memberRequest.getName(), memberRequest.getEmail(), memberRequest.getPassword(), "USER")); + Member member = memberRepository.save(new Member(memberRequest.getName(), memberRequest.getEmail(), memberRequest.getPassword(), "USER")); return new MemberResponse(member.getId(), member.getName(), member.getEmail()); } } From 552ebafb121cea36958475c90a97224084b00a31 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 13:33:09 +0900 Subject: [PATCH 27/79] =?UTF-8?q?feat=20:=20themeRepository=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/theme/ThemeDao.java | 82 ++++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/main/java/roomescape/theme/ThemeDao.java b/src/main/java/roomescape/theme/ThemeDao.java index 945341d8..b29183e2 100644 --- a/src/main/java/roomescape/theme/ThemeDao.java +++ b/src/main/java/roomescape/theme/ThemeDao.java @@ -1,41 +1,41 @@ -package roomescape.theme; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class ThemeDao { - private JdbcTemplate jdbcTemplate; - - public ThemeDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List findAll() { - return jdbcTemplate.query("SELECT * FROM theme where deleted = false", (rs, rowNum) -> new Theme( - rs.getLong("id"), - rs.getString("name"), - rs.getString("description") - )); - } - - public Theme save(Theme theme) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement("INSERT INTO theme(name, description) VALUES (?, ?)", new String[]{"id"}); - ps.setString(1, theme.getName()); - ps.setString(2, theme.getDescription()); - return ps; - }, keyHolder); - - return new Theme(keyHolder.getKey().longValue(), theme.getName(), theme.getDescription()); - } - - public void deleteById(Long id) { - jdbcTemplate.update("UPDATE theme SET deleted = true WHERE id = ?", id); - } -} +//package roomescape.theme; +// +//import org.springframework.jdbc.core.JdbcTemplate; +//import org.springframework.jdbc.support.GeneratedKeyHolder; +//import org.springframework.jdbc.support.KeyHolder; +//import org.springframework.stereotype.Repository; +// +//import java.util.List; +// +//@Repository +//public class ThemeDao { +// private JdbcTemplate jdbcTemplate; +// +// public ThemeDao(JdbcTemplate jdbcTemplate) { +// this.jdbcTemplate = jdbcTemplate; +// } +// +// public List findAll() { +// return jdbcTemplate.query("SELECT * FROM theme where deleted = false", (rs, rowNum) -> new Theme( +// rs.getLong("id"), +// rs.getString("name"), +// rs.getString("description") +// )); +// } +// +// public Theme save(Theme theme) { +// KeyHolder keyHolder = new GeneratedKeyHolder(); +// jdbcTemplate.update(connection -> { +// var ps = connection.prepareStatement("INSERT INTO theme(name, description) VALUES (?, ?)", new String[]{"id"}); +// ps.setString(1, theme.getName()); +// ps.setString(2, theme.getDescription()); +// return ps; +// }, keyHolder); +// +// return new Theme(keyHolder.getKey().longValue(), theme.getName(), theme.getDescription()); +// } +// +// public void deleteById(Long id) { +// jdbcTemplate.update("UPDATE theme SET deleted = true WHERE id = ?", id); +// } +//} From cde7be66387a2257f8b4c5689a1c6f3215107762 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 13:44:25 +0900 Subject: [PATCH 28/79] =?UTF-8?q?feat=20:=20reservationRepository=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reservation/ReservationService.java | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index b14a22d5..c109bda0 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -3,30 +3,52 @@ import org.springframework.stereotype.Service; import roomescape.reservation.dto.ReservationRequest; import roomescape.reservation.dto.ReservationResponse; +import roomescape.theme.Theme; +import roomescape.time.Time; import java.util.List; +import java.util.stream.Collectors; @Service public class ReservationService { - private ReservationDao reservationDao; + private final ReservationRepository reservationRepository; - public ReservationService(ReservationDao reservationDao) { - this.reservationDao = reservationDao; + public ReservationService(ReservationRepository reservationRepository) { + this.reservationRepository = reservationRepository; } 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()); + Reservation reservation = new Reservation( + null, + reservationRequest.getName(), + reservationRequest.getDate(), + new Time(reservationRequest.getTime(), null), + new Theme(reservationRequest.getTheme(), null, null) + ); + Reservation savedReservation = reservationRepository.save(reservation); + + return new ReservationResponse( + savedReservation.getId(), + savedReservation.getName(), + savedReservation.getTheme().getName(), + savedReservation.getDate(), + savedReservation.getTime().getValue() + ); } public void deleteById(Long id) { - reservationDao.deleteById(id); + reservationRepository.deleteById(id); } public List findAll() { - return reservationDao.findAll().stream() - .map(it -> new ReservationResponse(it.getId(), it.getName(), it.getTheme().getName(), it.getDate(), it.getTime().getValue())) - .toList(); + return reservationRepository.findAllWithDetails().stream() + .map(it -> new ReservationResponse( + it.getId(), + it.getName(), + it.getTheme().getName(), + it.getDate(), + it.getTime().getValue() + )) + .collect(Collectors.toList()); } } From a8c2c8cfd187491a38e1ad45e4c87c4dfd7b977a Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 13:45:46 +0900 Subject: [PATCH 29/79] =?UTF-8?q?feat=20:=20themeRepository=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/theme/ThemeController.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/roomescape/theme/ThemeController.java b/src/main/java/roomescape/theme/ThemeController.java index 7fa46abc..0bb0cbaf 100644 --- a/src/main/java/roomescape/theme/ThemeController.java +++ b/src/main/java/roomescape/theme/ThemeController.java @@ -7,27 +7,28 @@ import java.util.List; @RestController +@RequestMapping("/themes") public class ThemeController { - private ThemeDao themeDao; + private final ThemeRepository themeRepository; - public ThemeController(ThemeDao themeDao) { - this.themeDao = themeDao; + public ThemeController(ThemeRepository themeRepository) { + this.themeRepository = themeRepository; } - @PostMapping("/themes") + @PostMapping public ResponseEntity createTheme(@RequestBody Theme theme) { - Theme newTheme = themeDao.save(theme); + Theme newTheme = themeRepository.save(theme); return ResponseEntity.created(URI.create("/themes/" + newTheme.getId())).body(newTheme); } - @GetMapping("/themes") + @GetMapping public ResponseEntity> list() { - return ResponseEntity.ok(themeDao.findAll()); + return ResponseEntity.ok(themeRepository.findAll()); } - @DeleteMapping("/themes/{id}") + @DeleteMapping("/{id}") public ResponseEntity deleteTheme(@PathVariable Long id) { - themeDao.deleteById(id); + themeRepository.deleteById(id); return ResponseEntity.noContent().build(); } } From 1672171836ad481ea5f0c6c44137a42048048a4f Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 14:37:15 +0900 Subject: [PATCH 30/79] =?UTF-8?q?refactor=20:=20=EC=8A=A4=ED=82=A4?= =?UTF-8?q?=EB=A7=88=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/schema.sql | 60 ----------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 src/main/resources/schema.sql diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql deleted file mode 100644 index 75c947a5..00000000 --- a/src/main/resources/schema.sql +++ /dev/null @@ -1,60 +0,0 @@ -CREATE TABLE time -( - id BIGINT NOT NULL AUTO_INCREMENT, - time_value VARCHAR(20) NOT NULL, - deleted BOOLEAN NOT NULL DEFAULT FALSE, - PRIMARY KEY (id) -); - -CREATE TABLE theme -( - id BIGINT NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, - description VARCHAR(255) NOT NULL, - deleted BOOLEAN NOT NULL DEFAULT FALSE, - PRIMARY KEY (id) -); - -CREATE TABLE member -( - id BIGINT NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, - email VARCHAR(255) UNIQUE NOT NULL, - password VARCHAR(255) NOT NULL, - role VARCHAR(255) NOT NULL, - PRIMARY KEY (id) -); - -CREATE TABLE reservation -( - id BIGINT NOT NULL AUTO_INCREMENT, - date VARCHAR(255) NOT NULL, - name VARCHAR(255) NOT NULL, - time_id BIGINT, - theme_id BIGINT, - PRIMARY KEY (id), - FOREIGN KEY (time_id) REFERENCES time (id), - FOREIGN KEY (theme_id) REFERENCES theme (id) -); - -INSERT INTO member (name, email, password, role) -VALUES ('어드민', 'admin@email.com', 'password', 'ADMIN'), - ('브라운', 'brown@email.com', 'password', 'USER'); - -INSERT INTO theme (name, description) -VALUES ('테마1', '테마1입니다.'), - ('테마2', '테마2입니다.'), - ('테마3', '테마3입니다.'); - -INSERT INTO time (time_value) -VALUES ('10:00'), - ('12:00'), - ('14:00'), - ('16:00'), - ('18:00'), - ('20:00'); - -INSERT INTO reservation (name, date, time_id, theme_id) -VALUES ('어드민', '2024-03-01', 1, 1), - ('어드민', '2024-03-01', 2, 2), - ('어드민', '2024-03-01', 3, 3); \ No newline at end of file From 19c12907ece26bce9abde328c5b77cd00b628895 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 14:37:57 +0900 Subject: [PATCH 31/79] =?UTF-8?q?feat=20:=20jwt=EC=97=90=EC=84=9C=20member?= =?UTF-8?q?Dao=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/jwt/JwtService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/roomescape/jwt/JwtService.java b/src/main/java/roomescape/jwt/JwtService.java index 6168eeae..88b03fea 100644 --- a/src/main/java/roomescape/jwt/JwtService.java +++ b/src/main/java/roomescape/jwt/JwtService.java @@ -3,16 +3,16 @@ import io.jsonwebtoken.Claims; import org.springframework.stereotype.Service; import roomescape.member.Member; -import roomescape.member.MemberDao; +import roomescape.member.MemberRepository; @Service public class JwtService { private final JwtUtil jwtUtil; - private final MemberDao memberDao; + private final MemberRepository memberRepository; - public JwtService(JwtUtil jwtUtil, MemberDao memberDao) { + public JwtService(JwtUtil jwtUtil, MemberRepository memberRepository) { this.jwtUtil = jwtUtil; - this.memberDao = memberDao; + this.memberRepository = memberRepository; } public Long getUserIdFromToken(String token) { @@ -26,7 +26,7 @@ public Long getUserIdFromToken(String token) { public Member getMemberFromToken(String token) { Long userId = getUserIdFromToken(token); - Member member = memberDao.findById(userId); + Member member = memberRepository.findById(userId).get(); if (member == null) { throw new IllegalArgumentException("토큰으로부터 유저를 찾을 수 없습니다."); } From 60751e7719596f9ae6be863ea87acf28f7582937 Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 14:38:11 +0900 Subject: [PATCH 32/79] =?UTF-8?q?feat=20:=20login=EC=97=90=EC=84=9C=20dao?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/login/LoginController.java | 1 - src/main/java/roomescape/login/LoginService.java | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index 8e155754..d0b905f1 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -6,7 +6,6 @@ import org.springframework.web.bind.annotation.*; import roomescape.jwt.JwtService; import roomescape.member.Member; -import roomescape.member.MemberDao; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index 02fd604c..8632a728 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Service; import roomescape.jwt.JwtUtil; import roomescape.member.Member; -import roomescape.member.MemberDao; +import roomescape.member.MemberRepository; import java.util.HashMap; import java.util.Map; @@ -12,15 +12,15 @@ @Service public class LoginService { private final JwtUtil jwtUtil; - private final MemberDao memberDao; + private final MemberRepository memberRepository; - public LoginService(JwtUtil jwtUtil, MemberDao memberDao) { + public LoginService(JwtUtil jwtUtil, MemberRepository memberRepository) { this.jwtUtil = jwtUtil; - this.memberDao = memberDao; + this.memberRepository = memberRepository; } public String authenticate(String email, String password) { - Member member = memberDao.findByEmailAndPassword(email, password); + Member member = memberRepository.findByEmailAndPassword(email, password).get(); if (member == null) { throw new IllegalArgumentException("Invalid email or password"); } From b2f3feabbbd473516bb90f017440a61a0a9d86de Mon Sep 17 00:00:00 2001 From: hyebin Date: Wed, 8 Jan 2025 14:38:32 +0900 Subject: [PATCH 33/79] =?UTF-8?q?feat=20:=20timeDao=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/time/Time.java | 24 ++++-- src/main/java/roomescape/time/TimeDao.java | 82 +++++++++---------- .../java/roomescape/time/TimeRepository.java | 6 ++ .../java/roomescape/time/TimeService.java | 27 +++--- 4 files changed, 78 insertions(+), 61 deletions(-) diff --git a/src/main/java/roomescape/time/Time.java b/src/main/java/roomescape/time/Time.java index bc5a8f99..a49bbb98 100644 --- a/src/main/java/roomescape/time/Time.java +++ b/src/main/java/roomescape/time/Time.java @@ -1,9 +1,6 @@ package roomescape.time; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; @Entity public class Time { @@ -11,18 +8,21 @@ public class Time { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String value; + private String time_value; + + @Column(nullable = false) + private boolean deleted = false; public Time() { } public Time(Long id, String value) { this.id = id; - this.value = value; + this.time_value = value; } public Time(String value) { - this.value = value; + this.time_value = value; } public Long getId() { @@ -30,6 +30,14 @@ public Long getId() { } public String getValue() { - return value; + return time_value; + } + + public boolean isDeleted() { + return deleted; + } + + public void setDeleted(boolean deleted) { + this.deleted = deleted; } } diff --git a/src/main/java/roomescape/time/TimeDao.java b/src/main/java/roomescape/time/TimeDao.java index f39a9a32..776abffb 100644 --- a/src/main/java/roomescape/time/TimeDao.java +++ b/src/main/java/roomescape/time/TimeDao.java @@ -1,41 +1,41 @@ -package roomescape.time; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; - -import java.sql.PreparedStatement; -import java.util.List; - -@Repository -public class TimeDao { - private final JdbcTemplate jdbcTemplate; - - public TimeDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List