diff --git a/src/main/java/roomescape/auth/AdminInterceptor.java b/src/main/java/roomescape/auth/AdminInterceptor.java new file mode 100644 index 00000000..075f3461 --- /dev/null +++ b/src/main/java/roomescape/auth/AdminInterceptor.java @@ -0,0 +1,34 @@ +package roomescape.auth; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.SpringServletContainerInitializer; +import org.springframework.web.servlet.HandlerInterceptor; +import roomescape.member.Member; +import roomescape.member.MemberDao; +import roomescape.member.MemberService; + +@Component +public class AdminInterceptor implements HandlerInterceptor { + private final MemberDao memberDao; + private final MemberService memberService; + + public AdminInterceptor(MemberDao memberDao, MemberService memberService) { + this.memberDao = memberDao; + this.memberService = memberService; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Long memberId = memberService.checkLogin(request).getId(); + Member member = memberDao.findById(memberId); + + if (member == null || !member.getRole().equals("ADMIN")) { + response.setStatus(401); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/roomescape/auth/AuthController.java b/src/main/java/roomescape/auth/AuthController.java new file mode 100644 index 00000000..d0d32d37 --- /dev/null +++ b/src/main/java/roomescape/auth/AuthController.java @@ -0,0 +1,42 @@ +package roomescape.auth; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import roomescape.member.LoginMember; +import roomescape.member.MemberService; + +@Controller +public class AuthController { + MemberService memberService; + + public AuthController(MemberService memberService) { + this.memberService = memberService; + } + + @PostMapping("/login") + public ResponseEntity tokenLogin(@RequestBody LoginRequest request, HttpServletResponse response) { + + String accessToken = memberService.loginByEmailAndPassword(request); + + Cookie cookie = new Cookie("token", accessToken); + cookie.setHttpOnly(true); + cookie.setPath("/"); + response.addCookie(cookie); + + return ResponseEntity.ok().build(); + } + + @GetMapping("/login/check") + public ResponseEntity loginCheck(HttpServletRequest request) { + + LoginMember loginMember = memberService.checkLogin(request); + + return ResponseEntity.ok().body(loginMember); + } +} diff --git a/src/main/java/roomescape/auth/AuthWebConfiguration.java b/src/main/java/roomescape/auth/AuthWebConfiguration.java new file mode 100644 index 00000000..b923adbf --- /dev/null +++ b/src/main/java/roomescape/auth/AuthWebConfiguration.java @@ -0,0 +1,35 @@ +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 roomescape.member.MemberService; + +import java.util.List; + +@Configuration +public class AuthWebConfiguration implements WebMvcConfigurer { + + private final LoginMemberArgumentResolver loginMemberArgumentResolver; + private final AdminInterceptor adminInterceptor; + + public AuthWebConfiguration( + LoginMemberArgumentResolver loginMemberArgumentResolver, + AdminInterceptor adminInterceptor + ) { + this.loginMemberArgumentResolver = loginMemberArgumentResolver; + this.adminInterceptor = adminInterceptor; + } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(loginMemberArgumentResolver); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(adminInterceptor) + .addPathPatterns("/admin"); + } +} diff --git a/src/main/java/roomescape/auth/Authentication.java b/src/main/java/roomescape/auth/Authentication.java new file mode 100644 index 00000000..4485dd66 --- /dev/null +++ b/src/main/java/roomescape/auth/Authentication.java @@ -0,0 +1,11 @@ +package roomescape.auth; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface Authentication { +} diff --git a/src/main/java/roomescape/auth/Extractor.java b/src/main/java/roomescape/auth/Extractor.java new file mode 100644 index 00000000..fe4361b1 --- /dev/null +++ b/src/main/java/roomescape/auth/Extractor.java @@ -0,0 +1,30 @@ +package roomescape.auth; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; + +@Component +public class Extractor { + + public String extractToken(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + + for (Cookie cookie : cookies) { + if (cookie.getName().equals("token")) { + return cookie.getValue(); + } + } + return ""; + } + + public Long extractId(String token) { + return Long.valueOf(Jwts.parserBuilder() + .setSigningKey(Keys.hmacShaKeyFor("Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=".getBytes())) + .build() + .parseClaimsJws(token) + .getBody().getSubject()); + } +} diff --git a/src/main/java/roomescape/auth/LoginMemberArgumentResolver.java b/src/main/java/roomescape/auth/LoginMemberArgumentResolver.java new file mode 100644 index 00000000..5a7b29fa --- /dev/null +++ b/src/main/java/roomescape/auth/LoginMemberArgumentResolver.java @@ -0,0 +1,38 @@ +package roomescape.auth; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; +import roomescape.member.LoginMember; +import roomescape.member.MemberService; + +import java.lang.annotation.Annotation; + +@Component +public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + private MemberService memberService; + + public LoginMemberArgumentResolver(MemberService memberService) { + this.memberService = memberService; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(Annotation.class) + && parameter.getParameterType().equals(LoginMember.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + + HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + return memberService.checkLogin(request); + } +} diff --git a/src/main/java/roomescape/auth/LoginRequest.java b/src/main/java/roomescape/auth/LoginRequest.java new file mode 100644 index 00000000..e5e45fe3 --- /dev/null +++ b/src/main/java/roomescape/auth/LoginRequest.java @@ -0,0 +1,7 @@ +package roomescape.auth; + +public record LoginRequest( + String email, + String password +) { +} diff --git a/src/main/java/roomescape/auth/TokenProvider.java b/src/main/java/roomescape/auth/TokenProvider.java new file mode 100644 index 00000000..5849dcf4 --- /dev/null +++ b/src/main/java/roomescape/auth/TokenProvider.java @@ -0,0 +1,21 @@ +package roomescape.auth; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.springframework.stereotype.Component; +import roomescape.member.Member; + +@Component +public class TokenProvider { + private String secretKey = "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E="; + + public String createToken(Member member) { + String accessToken = Jwts.builder() + .setSubject(member.getId().toString()) + .claim("name", member.getName()) + .claim("role", member.getRole()) + .signWith(Keys.hmacShaKeyFor(secretKey.getBytes())) + .compact(); + return accessToken; + } +} diff --git a/src/main/java/roomescape/member/MemberResponse.java b/src/main/java/roomescape/member/LoginMember.java similarity index 60% rename from src/main/java/roomescape/member/MemberResponse.java rename to src/main/java/roomescape/member/LoginMember.java index b9fa3b97..1434855d 100644 --- a/src/main/java/roomescape/member/MemberResponse.java +++ b/src/main/java/roomescape/member/LoginMember.java @@ -1,16 +1,20 @@ package roomescape.member; -public class MemberResponse { +public class LoginMember { private Long id; private String name; private String email; - public MemberResponse(Long id, String name, String email) { + public LoginMember(Long id, String name, String email) { this.id = id; this.name = name; this.email = email; } + public static LoginMember from(Member member) { + return new LoginMember(member.getId(), member.getName(), member.getEmail()); + } + public Long getId() { return id; } diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index 881ae5e0..f6ccced3 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; @@ -21,7 +19,7 @@ public MemberController(MemberService memberService) { @PostMapping("/members") public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) { - MemberResponse member = memberService.createMember(memberRequest); + LoginMember member = memberService.createMember(memberRequest); return ResponseEntity.created(URI.create("/members/" + member.getId())).body(member); } diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java index 81f77f4c..0ecb2e53 100644 --- a/src/main/java/roomescape/member/MemberDao.java +++ b/src/main/java/roomescape/member/MemberDao.java @@ -40,16 +40,16 @@ public Member findByEmailAndPassword(String email, String password) { ); } - public Member findByName(String name) { + public Member findById(Long id) { return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", + "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") ), - name + id ); } } diff --git a/src/main/java/roomescape/member/MemberService.java b/src/main/java/roomescape/member/MemberService.java index ccaa8cba..901b686d 100644 --- a/src/main/java/roomescape/member/MemberService.java +++ b/src/main/java/roomescape/member/MemberService.java @@ -1,17 +1,60 @@ package roomescape.member; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Service; +import roomescape.auth.Extractor; +import roomescape.auth.LoginRequest; +import roomescape.auth.TokenProvider; + +import java.util.Arrays; @Service public class MemberService { - private MemberDao memberDao; + private final MemberDao memberDao; + private final TokenProvider tokenProvider; + private final Extractor extractor; - public MemberService(MemberDao memberDao) { + public MemberService(MemberDao memberDao, TokenProvider tokenProvider, Extractor extractor) { this.memberDao = memberDao; + this.tokenProvider = tokenProvider; + this.extractor = extractor; } - public MemberResponse createMember(MemberRequest memberRequest) { + public LoginMember createMember(MemberRequest memberRequest) { Member member = memberDao.save(new Member(memberRequest.getName(), memberRequest.getEmail(), memberRequest.getPassword(), "USER")); - return new MemberResponse(member.getId(), member.getName(), member.getEmail()); + return new LoginMember(member.getId(), member.getName(), member.getEmail()); + } + + public String loginByEmailAndPassword(LoginRequest request) { + try { + Member member = memberDao.findByEmailAndPassword(request.email(), request.password()); + return tokenProvider.createToken(member); + } catch (DataAccessException e) { + throw new IllegalArgumentException("로그인 정보가 불일치 합니다."); + } + } + + public LoginMember checkLogin(HttpServletRequest request) { + Arrays.stream(request.getCookies()) + .filter(cookie -> cookie.getName().equals("token")) + .findFirst() + .map(Cookie::getValue) + .orElseThrow(() -> new IllegalArgumentException("로그인이 필요합니다.")); + + String token = extractToken(request); + Long memberId = extractId(token); + + Member member = memberDao.findById(memberId); + return LoginMember.from(member); + } + + private String extractToken(HttpServletRequest request) { + return extractor.extractToken(request); + } + + private Long extractId(String token) { + return extractor.extractId(token); } } diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index b3bef399..aaae3d96 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.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.auth.Authentication; +import roomescape.member.LoginMember; import java.net.URI; import java.util.List; @@ -26,11 +23,21 @@ 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(@Authentication LoginMember loginMember ,@RequestBody ReservationRequest reservationRequest ) { + + if (reservationRequest.name() == null) { + reservationRequest = new ReservationRequest( + loginMember.getName(), + reservationRequest.date(), + reservationRequest.theme(), + reservationRequest.time() + ); + } + + if (reservationRequest.name() == null + || reservationRequest.date() == null + || reservationRequest.theme() == null + || reservationRequest.time() == null) { return ResponseEntity.badRequest().build(); } ReservationResponse reservation = reservationService.save(reservationRequest); diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java index a4972430..d75201e3 100644 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ b/src/main/java/roomescape/reservation/ReservationDao.java @@ -47,25 +47,25 @@ public Reservation save(ReservationRequest reservationRequest) { KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(connection -> { PreparedStatement ps = connection.prepareStatement("INSERT INTO reservation(date, name, theme_id, time_id) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, reservationRequest.getDate()); - ps.setString(2, reservationRequest.getName()); - ps.setLong(3, reservationRequest.getTheme()); - ps.setLong(4, reservationRequest.getTime()); + ps.setString(1, reservationRequest.date()); + ps.setString(2, reservationRequest.name()); + ps.setLong(3, reservationRequest.theme()); + ps.setLong(4, reservationRequest.time()); return ps; }, keyHolder); Time time = jdbcTemplate.queryForObject("SELECT * FROM time WHERE id = ?", (rs, rowNum) -> new Time(rs.getLong("id"), rs.getString("time_value")), - reservationRequest.getTime()); + reservationRequest.time()); Theme theme = jdbcTemplate.queryForObject("SELECT * FROM theme WHERE id = ?", (rs, rowNum) -> new Theme(rs.getLong("id"), rs.getString("name"), rs.getString("description")), - reservationRequest.getTheme()); + reservationRequest.theme()); return new Reservation( keyHolder.getKey().longValue(), - reservationRequest.getName(), - reservationRequest.getDate(), + reservationRequest.name(), + reservationRequest.date(), time, theme ); diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index 19f44124..55da337b 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -1,24 +1,9 @@ package roomescape.reservation; -public class ReservationRequest { - private String name; - private String date; - private Long theme; - private Long time; - - public String getName() { - return name; - } - - public String getDate() { - return date; - } - - public Long getTheme() { - return theme; - } - - public Long getTime() { - return time; - } +public record ReservationRequest( + String name, + String date, + Long theme, + Long time +) { } diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index bd331332..0350dc30 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -15,7 +15,7 @@ public ReservationService(ReservationDao reservationDao) { 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()); + return new ReservationResponse(reservation.getId(), reservationRequest.name(), reservation.getTheme().getName(), reservation.getDate(), reservation.getTime().getValue()); } public void deleteById(Long id) { 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..c1894e8f 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; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a0f33bba..3c25d07a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,11 +1,13 @@ spring.sql.init.encoding=utf-8 spring.h2.console.enabled=true spring.h2.console.path=/h2-console -spring.datasource.url=jdbc:h2:mem:database +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:tcp://localhost/~/database +spring.datasource.username=sa +spring.datasource.password= -#spring.jpa.show-sql=true #spring.jpa.properties.hibernate.format_sql=true +#spring.jpa.show-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 diff --git a/src/main/resources/templates/admin/index.html b/src/main/resources/templates/admin/index.html index 8c2de6ad..107b6982 100644 --- a/src/main/resources/templates/admin/index.html +++ b/src/main/resources/templates/admin/index.html @@ -1,56 +1,56 @@ - - - 방탈출 어드민 - - - + + + 방탈출 어드민 + + +
-

방탈출 어드민

+

방탈출 어드민

diff --git a/src/main/resources/templates/admin/reservation.html b/src/main/resources/templates/admin/reservation.html index b1ac0dae..7b27c6e9 100644 --- a/src/main/resources/templates/admin/reservation.html +++ b/src/main/resources/templates/admin/reservation.html @@ -1,74 +1,74 @@ - - - 방탈출 어드민 - - - + + + 방탈출 어드민 + + +
-

방탈출 예약 페이지

-
- -
-
- - - - - - - - - - - - - -
예약번호예약자테마날짜시간
+

방탈출 예약 페이지

+
+ +
+
+ + + + + + + + + + + + + +
예약번호예약자테마날짜시간
diff --git a/src/main/resources/templates/admin/theme.html b/src/main/resources/templates/admin/theme.html index 331a1169..be6f8337 100644 --- a/src/main/resources/templates/admin/theme.html +++ b/src/main/resources/templates/admin/theme.html @@ -1,72 +1,72 @@ - - - 방탈출 어드민 - - - + + + 방탈출 어드민 + + +
-

테마 관리 페이지

-
- -
-
- - - - - - - - - - - -
순서제목설명
+

테마 관리 페이지

+
+ +
+
+ + + + + + + + + + + +
순서제목설명
diff --git a/src/main/resources/templates/admin/time.html b/src/main/resources/templates/admin/time.html index 30a8e9bf..80c02511 100644 --- a/src/main/resources/templates/admin/time.html +++ b/src/main/resources/templates/admin/time.html @@ -1,71 +1,71 @@ - - - 방탈출 어드민 - - - + + + 방탈출 어드민 + + +
-

시간 관리 페이지

-
- -
-
- - - - - - - - - - -
순서시간
+

시간 관리 페이지

+
+ +
+
+ + + + + + + + + + +
순서시간
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 1341aff4..49897e37 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -1,50 +1,50 @@ - - - 방탈출 예약 페이지 - - - + + + 방탈출 예약 페이지 + + +
-

방탈출 예약 페이지

+

방탈출 예약 페이지

diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 5fbcebbf..308306ed 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -1,62 +1,62 @@ - - - Login - - - + + + Login + + +
-

Login

-
-
- -
-
- -
-
- - -
-
+

Login

+
+
+ +
+
+ +
+
+ + +
+
diff --git a/src/main/resources/templates/reservation-mine.html b/src/main/resources/templates/reservation-mine.html index 16096457..cde3a0e6 100644 --- a/src/main/resources/templates/reservation-mine.html +++ b/src/main/resources/templates/reservation-mine.html @@ -1,67 +1,67 @@ - - - 방탈출 어드민 - - - + + + 방탈출 어드민 + + +
-

내 예약

- - - -
- - - - - - - - - - - - -
테마날짜시간상태
+

내 예약

+ + + +
+ + + + + + + + + + + + +
테마날짜시간상태
diff --git a/src/main/resources/templates/reservation.html b/src/main/resources/templates/reservation.html index ce2ee771..5776e71b 100644 --- a/src/main/resources/templates/reservation.html +++ b/src/main/resources/templates/reservation.html @@ -1,82 +1,82 @@ - - - 방탈출 예약 페이지 - - - - - - + + + 방탈출 예약 페이지 + + + + + +
-

예약 페이지

-
- -
-

날짜 선택

-
-
-
-
+

예약 페이지

+
+ +
+

날짜 선택

+
+
+
+
- -
-

테마 선택

-
- -
-
+ +
+

테마 선택

+
+ +
+
- -
-

시간 선택

-
- -
+ +
+

시간 선택

+
+ +
+
-
- - - + + +
diff --git a/src/main/resources/templates/signup.html b/src/main/resources/templates/signup.html index 8965f2dd..4a72af19 100644 --- a/src/main/resources/templates/signup.html +++ b/src/main/resources/templates/signup.html @@ -1,65 +1,65 @@ - - - Signup - - - + + + Signup + + +
-

Signup

-
-
- - -
-
- - -
-
- - -
- -
+

Signup

+
+
+ + +
+
+ + +
+
+ + +
+ +
diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 6add784b..4be38696 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; @@ -19,9 +20,24 @@ public class MissionStepTest { @Test void 일단계() { + String token = createToken("admin@email.com", "password"); + 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("어드민"); + } + + private String createToken(String email, String password) { Map params = new HashMap<>(); - params.put("email", "admin@email.com"); - params.put("password", "password"); + params.put("email", email); + params.put("password", password); ExtractableResponse response = RestAssured.given().log().all() .contentType(ContentType.JSON) @@ -31,8 +47,59 @@ public class MissionStepTest { .statusCode(200) .extract(); - String token = response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; + return response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; + } - assertThat(token).isNotBlank(); + @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("브라운"); + } + + @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); } -} \ No newline at end of file +}