diff --git a/build.gradle b/build.gradle index 8d52aebc..7052c077 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ repositories { 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,9 +26,11 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.rest-assured:rest-assured:5.3.1' + testImplementation 'org.mockito:mockito-core:3.10.0' + runtimeOnly 'com.h2database:h2' } test { useJUnitPlatform() -} +} \ No newline at end of file diff --git a/src/main/java/roomescape/RoomescapeApplication.java b/src/main/java/roomescape/RoomescapeApplication.java index 2ca0f743..a2819b79 100644 --- a/src/main/java/roomescape/RoomescapeApplication.java +++ b/src/main/java/roomescape/RoomescapeApplication.java @@ -8,4 +8,4 @@ public class RoomescapeApplication { public static void main(String[] args) { SpringApplication.run(RoomescapeApplication.class, args); } -} +} \ No newline at end of file diff --git a/src/main/java/roomescape/WebConfig.java b/src/main/java/roomescape/WebConfig.java new file mode 100644 index 00000000..3ae96e7a --- /dev/null +++ b/src/main/java/roomescape/WebConfig.java @@ -0,0 +1,31 @@ +package roomescape; + +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 roomescape.interceptor.AdminInterceptor; +import roomescape.login.LoginMemberArgumentResolver; +import roomescape.member.MemberService; + +import java.util.List; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + private final MemberService memberService; + + public WebConfig(MemberService memberService) { + this.memberService = memberService; + } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new LoginMemberArgumentResolver(memberService)); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new AdminInterceptor(memberService)) + .addPathPatterns("/admin/**"); + } +} diff --git a/src/main/java/roomescape/interceptor/AdminInterceptor.java b/src/main/java/roomescape/interceptor/AdminInterceptor.java new file mode 100644 index 00000000..9bf8c064 --- /dev/null +++ b/src/main/java/roomescape/interceptor/AdminInterceptor.java @@ -0,0 +1,62 @@ +package roomescape.interceptor; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.servlet.HandlerInterceptor; +import roomescape.member.MemberService; +import roomescape.member.ViewMemberResponse; + +import java.security.Key; +import java.util.Arrays; + +public class AdminInterceptor implements HandlerInterceptor { + private static final String SECRET_KEY = "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E="; + private static final Key KEY = Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); + private final MemberService memberService; + + public AdminInterceptor(MemberService memberService) { + this.memberService = memberService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + Cookie tokenCookie = Arrays.stream(cookies) + .filter(cookie -> "token".equals(cookie.getName())) + .findFirst() + .orElse(null); + + if (tokenCookie == null) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + try { + String token = tokenCookie.getValue(); + Long memberId = Long.valueOf(Jwts.parserBuilder() + .setSigningKey(KEY) + .build() + .parseClaimsJws(token) + .getBody().getSubject()); + + ViewMemberResponse member = memberService.findMemberById(memberId); + if (member == null || !member.getRole().equals("ADMIN")) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + } catch (Exception e) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + + return true; + } +} diff --git a/src/main/java/roomescape/login/LoginMember.java b/src/main/java/roomescape/login/LoginMember.java new file mode 100644 index 00000000..21ad8d29 --- /dev/null +++ b/src/main/java/roomescape/login/LoginMember.java @@ -0,0 +1,31 @@ +package roomescape.login; + +public class LoginMember { + private Long id; + private String name; + private String email; + private String role; + + public LoginMember(Long id, String name, String email, String role) { + this.id = id; + this.name = name; + this.email = email; + this.role = role; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public String getRole() { + return role; + } +} \ No newline at end of file diff --git a/src/main/java/roomescape/login/LoginMemberArgumentResolver.java b/src/main/java/roomescape/login/LoginMemberArgumentResolver.java new file mode 100644 index 00000000..12890ca1 --- /dev/null +++ b/src/main/java/roomescape/login/LoginMemberArgumentResolver.java @@ -0,0 +1,58 @@ +package roomescape.login; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.springframework.core.MethodParameter; +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 jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import roomescape.login.LoginMember; +import roomescape.member.MemberService; +import roomescape.member.ViewMemberResponse; + +import java.security.Key; + +public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + private static final String SECRET_KEY = "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E="; + private static final Key KEY = Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); + private final MemberService memberService; + + public LoginMemberArgumentResolver(MemberService memberService) { + this.memberService = memberService; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().equals(LoginMember.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + if (request != null) { + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("token")) { + String token = cookie.getValue(); + Long memberId = Long.valueOf(Jwts.parserBuilder() + .setSigningKey(KEY) + .build() + .parseClaimsJws(token) + .getBody().getSubject()); + + ViewMemberResponse member = memberService.findMemberById(memberId); + if (member != null) { + return new LoginMember(member.getId(), member.getName(), member.getEmail(), member.getRole()); + } + } + } + } + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/roomescape/member/Member.java b/src/main/java/roomescape/member/Member.java index 903aaa9b..eeb97683 100644 --- a/src/main/java/roomescape/member/Member.java +++ b/src/main/java/roomescape/member/Member.java @@ -1,10 +1,23 @@ 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(Long id, String name, String email, String role) { @@ -13,7 +26,6 @@ public Member(Long id, String name, String email, String role) { this.email = email; this.role = role; } - public Member(String name, String email, String password, String role) { this.name = name; this.email = email; @@ -21,23 +33,23 @@ public Member(String name, String email, String password, String role) { this.role = role; } + public Member() { + + } + public Long getId() { return id; } - public String getName() { return name; } - public String getEmail() { return email; } - public String getPassword() { return password; } - public String getRole() { return role; } -} +} \ No newline at end of file diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index 881ae5e0..dd9a8baf 100644 --- a/src/main/java/roomescape/member/MemberController.java +++ b/src/main/java/roomescape/member/MemberController.java @@ -1,19 +1,23 @@ package roomescape.member; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.net.URI; +import java.security.Key; +import java.util.Map; @RestController public class MemberController { - private MemberService memberService; + private final MemberService memberService; + private static final String SECRET_KEY = "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E="; + private static final Key KEY = Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); public MemberController(MemberService memberService) { this.memberService = memberService; @@ -25,8 +29,67 @@ public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) { return ResponseEntity.created(URI.create("/members/" + member.getId())).body(member); } + @PostMapping("/login") + public ResponseEntity login(@RequestBody Map params, HttpServletResponse response) { + String email = params.get("email"); + String password = params.get("password"); + + ViewMemberResponse viewMemberResponse = memberService.findMemberByEmailAndPassword(email, password); + + if (viewMemberResponse != null) { + String token = Jwts.builder() + .setSubject(viewMemberResponse.getId().toString()) + .claim("name", viewMemberResponse.getName()) + .claim("role", viewMemberResponse.getRole()) + .signWith(KEY) + .compact(); + + Cookie cookie = new Cookie("token", token); + cookie.setHttpOnly(true); + cookie.setPath("/"); + response.addCookie(cookie); + + return ResponseEntity.ok().build(); + } + + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + @GetMapping("/login/check") + public ResponseEntity checkLogin(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + String token = extractTokenFromCookie(cookies); + if (!token.isEmpty()) { + try { + Long memberId = Long.valueOf(Jwts.parserBuilder() + .setSigningKey(KEY) + .build() + .parseClaimsJws(token) + .getBody().getSubject()); + + ViewMemberResponse viewMemberResponse = memberService.findMemberById(memberId); + MemberResponse memberResponse = new MemberResponse(viewMemberResponse.getId(), viewMemberResponse.getName(), viewMemberResponse.getEmail()); + return ResponseEntity.ok(memberResponse); + } catch (Exception e) { + return ResponseEntity.status(401).build(); + } + } + } + return ResponseEntity.status(401).build(); + } + + private String extractTokenFromCookie(Cookie[] cookies) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("token")) { + return cookie.getValue(); + } + } + return ""; + } + @PostMapping("/logout") - public ResponseEntity logout(HttpServletResponse response) { + public ResponseEntity logout(HttpServletResponse response) { Cookie cookie = new Cookie("token", ""); cookie.setHttpOnly(true); cookie.setPath("/"); diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java index 81f77f4c..38181541 100644 --- a/src/main/java/roomescape/member/MemberDao.java +++ b/src/main/java/roomescape/member/MemberDao.java @@ -1,3 +1,4 @@ +/* package roomescape.member; import org.springframework.jdbc.core.JdbcTemplate; @@ -7,7 +8,7 @@ @Repository public class MemberDao { - private JdbcTemplate jdbcTemplate; + private final JdbcTemplate jdbcTemplate; public MemberDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; @@ -24,16 +25,17 @@ public Member save(Member member) { return ps; }, keyHolder); - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER"); + return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), member.getPassword(), member.getRole()); } public Member findByEmailAndPassword(String email, String password) { return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", + "SELECT id, name, email, password, role FROM member WHERE email = ? AND password = ?", (rs, rowNum) -> new Member( rs.getLong("id"), rs.getString("name"), rs.getString("email"), + rs.getString("password"), rs.getString("role") ), email, password @@ -42,14 +44,30 @@ public Member findByEmailAndPassword(String email, String password) { public Member findByName(String name) { return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", + "SELECT id, name, email, password, role FROM member WHERE name = ?", (rs, rowNum) -> new Member( rs.getLong("id"), rs.getString("name"), rs.getString("email"), + rs.getString("password"), rs.getString("role") ), name ); } + + public Member findById(Long id) { + return jdbcTemplate.queryForObject( + "SELECT id, name, email, password, role FROM member WHERE id = ?", + (rs, rowNum) -> new Member( + rs.getLong("id"), + rs.getString("name"), + rs.getString("email"), + rs.getString("password"), + rs.getString("role") + ), + id + ); + } } +*/ \ No newline at end of file diff --git a/src/main/java/roomescape/member/MemberRepository.java b/src/main/java/roomescape/member/MemberRepository.java new file mode 100644 index 00000000..3d515722 --- /dev/null +++ b/src/main/java/roomescape/member/MemberRepository.java @@ -0,0 +1,8 @@ +package roomescape.member; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { + Member findByEmailAndPassword(String email, String password); + Member findByName(String name); +} diff --git a/src/main/java/roomescape/member/MemberService.java b/src/main/java/roomescape/member/MemberService.java index ccaa8cba..4925b5b9 100644 --- a/src/main/java/roomescape/member/MemberService.java +++ b/src/main/java/roomescape/member/MemberService.java @@ -4,14 +4,38 @@ @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()); } + + public ViewMemberResponse findMemberByEmailAndPassword(String email, String password) { + Member member = memberRepository.findByEmailAndPassword(email, password); + if (member != null) { + return new ViewMemberResponse(member.getId(), member.getName(), member.getEmail(), member.getRole()); + } + return null; + } + + public ViewMemberResponse findMemberById(Long id) { + Member member = memberRepository.findById(id).orElse(null); + if (member != null) { + return new ViewMemberResponse(member.getId(), member.getName(), member.getEmail(), member.getRole()); + } + return null; + } + + public ViewMemberResponse findMemberByName(String name) { + Member member = memberRepository.findByName(name); + if (member != null) { + return new ViewMemberResponse(member.getId(), member.getName(), member.getEmail(), member.getRole()); + } + return null; + } } diff --git a/src/main/java/roomescape/member/ViewMemberResponse.java b/src/main/java/roomescape/member/ViewMemberResponse.java new file mode 100644 index 00000000..a400bb40 --- /dev/null +++ b/src/main/java/roomescape/member/ViewMemberResponse.java @@ -0,0 +1,31 @@ +package roomescape.member; + +public class ViewMemberResponse { + private Long id; + private String name; + private String email; + private String role; + + public ViewMemberResponse(Long id, String name, String email, String role) { + this.id = id; + this.name = name; + this.email = email; + this.role = role; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public String getRole() { + return role; + } +} diff --git a/src/main/java/roomescape/reservation/MyReservationResponse.java b/src/main/java/roomescape/reservation/MyReservationResponse.java new file mode 100644 index 00000000..638448ec --- /dev/null +++ b/src/main/java/roomescape/reservation/MyReservationResponse.java @@ -0,0 +1,57 @@ +package roomescape.reservation; + +public class MyReservationResponse { + private Long reservationId; + private String theme; + private String date; + private String time; + private String status; + + public MyReservationResponse(Long reservationId, String theme, String date, String time, String status) { + this.reservationId = reservationId; + this.theme = theme; + this.date = date; + this.time = time; + this.status = status; + } + + public Long getReservationId() { + return reservationId; + } + + public void setReservationId(Long reservationId) { + this.reservationId = reservationId; + } + + public String getTheme() { + return theme; + } + + public void setTheme(String theme) { + this.theme = theme; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/src/main/java/roomescape/reservation/Reservation.java b/src/main/java/roomescape/reservation/Reservation.java index 83a7edf1..cfb4afe5 100644 --- a/src/main/java/roomescape/reservation/Reservation.java +++ b/src/main/java/roomescape/reservation/Reservation.java @@ -1,51 +1,97 @@ package roomescape.reservation; +import jakarta.persistence.*; import roomescape.theme.Theme; import roomescape.time.Time; +import roomescape.member.Member; +@Entity public class Reservation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; + private String date; + + @ManyToOne + @JoinColumn(name = "time_id") private Time time; + + @ManyToOne + @JoinColumn(name = "theme_id") private Theme theme; - public Reservation(Long id, String name, String date, Time time, Theme theme) { + @ManyToOne + @JoinColumn(name = "member_id") + private Member member; + + public Reservation() {} + + public Reservation(Long id, String name, String date, Time time, Theme theme, Member member) { this.id = id; this.name = name; this.date = date; this.time = time; this.theme = theme; + this.member = member; } - public Reservation(String name, String date, Time time, Theme theme) { + public Reservation(String name, String date, Time time, Theme theme, Member member) { this.name = name; this.date = date; this.time = time; this.theme = theme; + this.member = member; } - public Reservation() { - - } - + // Getters and Setters public Long getId() { return id; } + public void setId(Long id) { + this.id = id; + } + public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + public String getDate() { return date; } + public void setDate(String date) { + this.date = date; + } + public Time getTime() { return time; } + public void setTime(Time time) { + this.time = time; + } + public Theme getTheme() { return theme; } + + public void setTheme(Theme theme) { + this.theme = theme; + } + + public Member getMember() { + return member; + } + + public void setMember(Member member) { + this.member = member; + } } diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index b3bef399..625bd92d 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -1,23 +1,22 @@ package roomescape.reservation; 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.LoginMember; +import roomescape.member.MemberService; +import roomescape.member.ViewMemberResponse; import java.net.URI; import java.util.List; @RestController public class ReservationController { - private final ReservationService reservationService; + private final MemberService memberService; - public ReservationController(ReservationService reservationService) { + public ReservationController(ReservationService reservationService, MemberService memberService) { this.reservationService = reservationService; + this.memberService = memberService; } @GetMapping("/reservations") @@ -26,13 +25,18 @@ public List list() { } @PostMapping("/reservations") - public ResponseEntity create(@RequestBody ReservationRequest reservationRequest) { - if (reservationRequest.getName() == null - || reservationRequest.getDate() == null - || reservationRequest.getTheme() == null - || reservationRequest.getTime() == null) { + public ResponseEntity create(@RequestBody ReservationRequest reservationRequest, LoginMember loginMember) { + if (reservationRequest.getDate() == null || reservationRequest.getTheme() == null || reservationRequest.getTime() == null) { + return ResponseEntity.badRequest().build(); + } + + String memberName = reservationRequest.getName() != null ? reservationRequest.getName() : loginMember.getName(); + ViewMemberResponse member = memberService.findMemberByName(memberName); + if (member == null) { return ResponseEntity.badRequest().build(); } + + reservationRequest.setName(member.getName()); // 예약자의 이름을 설정 ReservationResponse reservation = reservationService.save(reservationRequest); return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); @@ -43,4 +47,10 @@ public ResponseEntity delete(@PathVariable Long id) { reservationService.deleteById(id); return ResponseEntity.noContent().build(); } + + @GetMapping("/reservations-mine") + public ResponseEntity> myReservations(LoginMember loginMember) { + List reservations = reservationService.findReservationsByMemberId(loginMember.getId()); + return ResponseEntity.ok(reservations); + } } diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java index a4972430..c7dbf461 100644 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ b/src/main/java/roomescape/reservation/ReservationDao.java @@ -1,4 +1,4 @@ -package roomescape.reservation; +/*package roomescape.reservation; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -12,7 +12,6 @@ @Repository public class ReservationDao { - private final JdbcTemplate jdbcTemplate; public ReservationDao(JdbcTemplate jdbcTemplate) { @@ -27,7 +26,6 @@ public List findAll() { "FROM reservation r " + "JOIN theme t ON r.theme_id = t.id " + "JOIN time ti ON r.time_id = ti.id", - (rs, rowNum) -> new Reservation( rs.getLong("reservation_id"), rs.getString("reservation_name"), @@ -82,7 +80,7 @@ public List findReservationsByDateAndTheme(String date, Long themeI "ti.id AS time_id, ti.time_value AS time_value " + "FROM reservation r " + "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id" + + "JOIN time ti ON r.time_id = ti.id " + "WHERE r.date = ? AND r.theme_id = ?", new Object[]{date, themeId}, (rs, rowNum) -> new Reservation( @@ -125,3 +123,4 @@ public List findByDateAndThemeId(String date, Long themeId) { ))); } } +*/ \ No newline at end of file diff --git a/src/main/java/roomescape/reservation/ReservationRepository.java b/src/main/java/roomescape/reservation/ReservationRepository.java new file mode 100644 index 00000000..fbad5993 --- /dev/null +++ b/src/main/java/roomescape/reservation/ReservationRepository.java @@ -0,0 +1,10 @@ +package roomescape.reservation; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ReservationRepository extends JpaRepository { + List findByDateAndThemeId(String date, Long themeId); + List findByMemberId(Long memberId); +} diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index 19f44124..d0115d26 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -6,19 +6,48 @@ public class ReservationRequest { private Long theme; private Long time; + // 기본 생성자 + public ReservationRequest() {} + + // 모든 필드를 초기화하는 생성자 + public ReservationRequest(String name, String date, Long theme, Long time) { + this.name = name; + this.date = date; + this.theme = theme; + this.time = time; + } + + // Getter 및 Setter 메서드 + public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + public String getDate() { return date; } + public void setDate(String date) { + this.date = date; + } + public Long getTheme() { return theme; } + public void setTheme(Long theme) { + this.theme = theme; + } + public Long getTime() { return time; } + + public void setTime(Long time) { + this.time = time; + } } diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index bd331332..b3ad1cef 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -1,29 +1,59 @@ package roomescape.reservation; import org.springframework.stereotype.Service; +import roomescape.theme.Theme; +import roomescape.theme.ThemeRepository; +import roomescape.time.Time; +import roomescape.time.TimeRepository; import java.util.List; +import java.util.stream.Collectors; @Service public class ReservationService { - private ReservationDao reservationDao; + private final ReservationRepository reservationRepository; + private final TimeRepository timeRepository; + private final ThemeRepository themeRepository; + + public ReservationService(ReservationRepository reservationRepository, TimeRepository timeRepository, ThemeRepository themeRepository) { + this.reservationRepository = reservationRepository; + this.timeRepository = timeRepository; + this.themeRepository = themeRepository; + } - public ReservationService(ReservationDao reservationDao) { - this.reservationDao = reservationDao; + public List findReservationsByMemberId(Long memberId) { + return reservationRepository.findByMemberId(memberId).stream() + .map(reservation -> new MyReservationResponse( + reservation.getId(), + reservation.getTheme().getName(), + reservation.getDate(), + reservation.getTime().getValue(), + "예약" + )) + .collect(Collectors.toList()); } 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()); + Time time = timeRepository.findById(reservationRequest.getTime()).orElseThrow(() -> new IllegalArgumentException("Invalid time ID")); + Theme theme = themeRepository.findById(reservationRequest.getTheme()).orElseThrow(() -> new IllegalArgumentException("Invalid theme ID")); + + Reservation reservation = reservationRepository.save(new Reservation( + reservationRequest.getName(), + reservationRequest.getDate(), + time, + theme, + null + )); + + return new ReservationResponse(reservation.getId(), reservation.getName(), reservation.getTheme().getName(), reservation.getDate(), reservation.getTime().getValue()); } public void deleteById(Long id) { - reservationDao.deleteById(id); + reservationRepository.deleteById(id); } public List findAll() { - return reservationDao.findAll().stream() + return reservationRepository.findAll().stream() .map(it -> new ReservationResponse(it.getId(), it.getName(), it.getTheme().getName(), it.getDate(), it.getTime().getValue())) .toList(); } diff --git a/src/main/java/roomescape/theme/Theme.java b/src/main/java/roomescape/theme/Theme.java index 430a6239..cfda98fe 100644 --- a/src/main/java/roomescape/theme/Theme.java +++ b/src/main/java/roomescape/theme/Theme.java @@ -1,12 +1,21 @@ 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; - public Theme() { - } + public Theme() {} public Theme(Long id, String name, String description) { this.id = id; @@ -23,11 +32,23 @@ public Long getId() { return id; } + public void setId(Long id) { + this.id = id; + } + public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + public String getDescription() { return description; } + + public void setDescription(String description) { + this.description = description; + } } diff --git a/src/main/java/roomescape/theme/ThemeController.java b/src/main/java/roomescape/theme/ThemeController.java index 03bca41a..e2ad8ba9 100644 --- a/src/main/java/roomescape/theme/ThemeController.java +++ b/src/main/java/roomescape/theme/ThemeController.java @@ -1,38 +1,33 @@ 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; @RestController 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") 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") public ResponseEntity> list() { - return ResponseEntity.ok(themeDao.findAll()); + return ResponseEntity.ok(themeRepository.findAll()); } @DeleteMapping("/themes/{id}") public ResponseEntity deleteTheme(@PathVariable Long id) { - themeDao.deleteById(id); + themeRepository.deleteById(id); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/roomescape/theme/ThemeDao.java b/src/main/java/roomescape/theme/ThemeDao.java index 945341d8..509cfa73 100644 --- a/src/main/java/roomescape/theme/ThemeDao.java +++ b/src/main/java/roomescape/theme/ThemeDao.java @@ -1,4 +1,4 @@ -package roomescape.theme; +/*package roomescape.theme; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -39,3 +39,4 @@ public void deleteById(Long id) { jdbcTemplate.update("UPDATE theme SET deleted = true WHERE id = ?", id); } } +*/ \ No newline at end of file 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..ce6be850 100644 --- a/src/main/java/roomescape/time/Time.java +++ b/src/main/java/roomescape/time/Time.java @@ -1,9 +1,18 @@ package roomescape.time; +import jakarta.persistence.*; + +@Entity public class Time { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(name = "time_value") private String value; + public Time() {} + public Time(Long id, String value) { this.id = id; this.value = value; @@ -13,15 +22,20 @@ public Time(String value) { this.value = value; } - public Time() { - - } - public Long getId() { return id; } + public void setId(Long id) { + this.id = id; + } + public String getValue() { return value; } + + public void setValue(String value) { + this.value = value; + } + } diff --git a/src/main/java/roomescape/time/TimeDao.java b/src/main/java/roomescape/time/TimeDao.java index f39a9a32..b489638f 100644 --- a/src/main/java/roomescape/time/TimeDao.java +++ b/src/main/java/roomescape/time/TimeDao.java @@ -1,4 +1,4 @@ -package roomescape.time; +/*package roomescape.time; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -39,3 +39,4 @@ public void deleteById(Long id) { jdbcTemplate.update("UPDATE time SET deleted = true WHERE id = ?", id); } } +*/ \ No newline at end of file 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/java/roomescape/time/TimeService.java b/src/main/java/roomescape/time/TimeService.java index 7d0cb9b0..df59bcfd 100644 --- a/src/main/java/roomescape/time/TimeService.java +++ b/src/main/java/roomescape/time/TimeService.java @@ -2,23 +2,23 @@ import org.springframework.stereotype.Service; import roomescape.reservation.Reservation; -import roomescape.reservation.ReservationDao; +import roomescape.reservation.ReservationRepository; import java.util.List; @Service public class TimeService { - private TimeDao timeDao; - private ReservationDao reservationDao; + private final TimeRepository timeRepository; + private final ReservationRepository reservationRepository; - public TimeService(TimeDao timeDao, ReservationDao reservationDao) { - this.timeDao = timeDao; - this.reservationDao = reservationDao; + public TimeService(TimeRepository timeRepository, ReservationRepository reservationRepository) { + this.timeRepository = timeRepository; + this.reservationRepository = reservationRepository; } public List getAvailableTime(String date, Long themeId) { - List reservations = reservationDao.findByDateAndThemeId(date, themeId); - List