Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2-2 로그인 리팩토링 #50

Open
wants to merge 9 commits into
base: dyrlqhffo
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package roomescape.argumentresolver;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.util.StringUtils;
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.dto.auth.AuthCheckResponse;
import roomescape.exception.ErrorCode;
import roomescape.exception.custom.AuthorizationException;
import roomescape.jwt.JwtTokenProvider;
import roomescape.service.AuthService;
import roomescape.util.CookieUtil;

import java.util.Optional;


public class LoginArgumentResolver implements HandlerMethodArgumentResolver {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArgumentResolver 잘 활용해주셨네요 👍


private final AuthService authService;
public LoginArgumentResolver(AuthService authService) {
this.authService = authService;
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(LoginUser.class);
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
String token = CookieUtil.extractTokenFromCookie(request.getCookies())
.orElseThrow(() -> new AuthorizationException(ErrorCode.UNAUTHORIZED_USER, "로그인한 유저만 이용가능합니다."));
return authService.findUserFromToken(token);
}
}
11 changes: 11 additions & 0 deletions src/main/java/roomescape/argumentresolver/LoginUser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package roomescape.argumentresolver;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
24 changes: 24 additions & 0 deletions src/main/java/roomescape/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package roomescape.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import roomescape.argumentresolver.LoginArgumentResolver;
import roomescape.jwt.JwtTokenProvider;
import roomescape.service.AuthService;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {
private final AuthService authService;

public WebConfig(JwtTokenProvider jwtTokenProvider, AuthService authService) {
this.authService = authService;
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginArgumentResolver(authService));
}
}
33 changes: 17 additions & 16 deletions src/main/java/roomescape/controller/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import roomescape.argumentresolver.LoginUser;
import roomescape.domain.User;
import roomescape.dto.auth.AuthCheckResponse;
import roomescape.dto.auth.AuthLoginRequest;
import roomescape.dto.auth.AuthUserResponse;
import roomescape.dto.auth.UserResponse;
import roomescape.exception.ErrorCode;
import roomescape.exception.custom.AuthorizationException;
import roomescape.exception.custom.CookieNotFoundException;
import roomescape.service.AuthService;
import roomescape.util.CookieUtil;

import java.util.Arrays;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

불필요한 import 문과 공백들은 제거 부탁드려요!

import java.util.List;
import java.util.Optional;

@RestController
Expand All @@ -28,36 +33,32 @@ public AuthController(AuthService authService) {
this.authService = authService;
}

@GetMapping("/users")
public ResponseEntity<List<UserResponse>> findUsers() {
return ResponseEntity.ok().body(authService.findUsers());
}

@PostMapping("/login")
public ResponseEntity<Void> authLogin(@RequestBody AuthLoginRequest request,
HttpServletResponse response) {
String token = authService.authLogin(request);
System.out.println(token);
Cookie cookie = CookieUtil.createCookie(token);
response.addCookie(cookie);
return ResponseEntity.ok().build();

}

@GetMapping("/login/check")
public ResponseEntity<AuthCheckResponse> checkLogin(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
String accessToken = CookieUtil.extractTokenFromCookie(cookies)
.orElseThrow(() -> new AuthorizationException(ErrorCode.UNAUTHORIZED_USER, "다시 로그인 해주세요."));
AuthCheckResponse userResponse = authService.findUserFromToken(accessToken);
return ResponseEntity.ok(userResponse);
public ResponseEntity<AuthCheckResponse> checkLogin(@LoginUser User user) {
return ResponseEntity.ok(authService.checkUser(user));
}

@PostMapping("/logout")
public ResponseEntity<Cookie> logout(HttpServletRequest request, HttpServletResponse response) {
Cookie findCookie = Arrays.stream(request.getCookies())
.filter(cookie -> cookie.getName().equals("token"))
.findFirst()
.orElseThrow(()-> new CookieNotFoundException(ErrorCode.COOKIE_NOT_FOUND, "로그인이 되어 있지 않습니다."));

findCookie.setMaxAge(0);
response.addCookie(findCookie);
return ResponseEntity.ok(findCookie);
public ResponseEntity<Cookie> logout(@LoginUser User user, HttpServletResponse response) {
Cookie cookie = CookieUtil.createCookie("");
cookie.setMaxAge(0);
response.addCookie(cookie);
return ResponseEntity.ok().build();
}

}
32 changes: 26 additions & 6 deletions src/main/java/roomescape/controller/ReservationController.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package roomescape.controller;

import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import roomescape.argumentresolver.LoginUser;
import roomescape.domain.Role;
import roomescape.domain.User;
import roomescape.dto.reservation.ReservationsResponse;
import roomescape.dto.reservation.create.ReservationCreateRequest;
import roomescape.dto.reservation.create.ReservationCreateResponse;
import roomescape.exception.ErrorCode;
import roomescape.exception.custom.AuthorizationException;
import roomescape.service.ReservationService;

import java.net.URI;
import java.util.List;

@RestController
@RequestMapping("/reservations")
@RequestMapping
public class ReservationController {

private final ReservationService reservationService;
Expand All @@ -21,21 +26,36 @@ public ReservationController(ReservationService reservationService) {
this.reservationService = reservationService;
}

@GetMapping
@GetMapping("/reservations")
public ResponseEntity<List<ReservationsResponse>> findReservations() {
List<ReservationsResponse> list = reservationService.findReservations();
return ResponseEntity.ok().body(list);
}

@PostMapping
public ResponseEntity<ReservationCreateResponse> create(@Valid @RequestBody ReservationCreateRequest dto) {
@PostMapping("/reservations")
public ResponseEntity<ReservationCreateResponse> create(@Valid @RequestBody ReservationCreateRequest dto,
@LoginUser User user) {
dto.addUserName(user.getName());
ReservationCreateResponse reservation = reservationService.createReservation(dto);
return ResponseEntity.ok().body(reservation);
}

@DeleteMapping("/{id}")
@DeleteMapping("/reservations/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
reservationService.deleteReservation(id);
return ResponseEntity.ok().build();
}

@PostMapping("/admin/reservations")
public ResponseEntity<ReservationCreateResponse> createAdminReservation(
@Valid @RequestBody ReservationCreateRequest requestDto,
@LoginUser User user){

if(user.getRole() != Role.ADMIN){
throw new AuthorizationException(ErrorCode.UNAUTHORIZED_ADMIN, "관리자 권한이 필요합니다.");
}
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번 단계에서 어느정도 admin 기능에 대한 권한 제어를 해주셨네요 👍
다음 단계 요구사항으로 interceptor 를 통해 검증하도록 바꾸면서 interceptor 의 역할에 대해 더 깊게 체감할 수 있겠군요!


ReservationCreateResponse reservation = reservationService.createReservation(requestDto);
return ResponseEntity.status(HttpStatus.CREATED).body(reservation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ResponseEntity<Void> delete(@PathVariable Long id) {
reservationTimeService.deleteTime(id);
return ResponseEntity.ok().build();
}

//예약 가능시간 조회
@GetMapping("/available")
public ResponseEntity<List<ReservationTimeAvailableResponse>> availableTime(@RequestParam String date,
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/roomescape/controller/ThemeController.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ public ThemeController(ThemeService themeService) {
this.themeService = themeService;
}

/**
* 테마 관리 페이지의 테마
* 순서 제목 설명 썸네일URL
*
* @return
*/
@GetMapping
public ResponseEntity<List<ThemeResponse>> findThemes() {
return ResponseEntity.ok().body(themeService.findThemes());
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/roomescape/domain/Reservation.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ public class Reservation {
private LocalDate date;
private ReservationTime time;
private Theme theme;
// private User user;

public Reservation() {
}

public Reservation(Long id, String name, String date, Long timeId, String startAt, Long themeId, String themeName) {
public Reservation(Long id, String userName, String date, Long timeId, String startAt, Long themeId, String themeName) {
this.id = id;
this.name = name;
this.name = userName;
this.date = LocalDate.parse(date);
this.time = new ReservationTime(timeId, startAt);
this.theme = new Theme(themeId, themeName);
}

public Reservation(Long id, String name, String date, ReservationTime time, Theme theme) {
public Reservation(Long id, String userName, String date, ReservationTime time, Theme theme) {
this.id = id;
this.name = name;
this.name = userName;
this.date = LocalDate.parse(date);
this.time = new ReservationTime(time.getId(), time.getStartAt().toString());
this.theme = new Theme(theme.getId(), theme.getName(), theme.getDescription(), theme.getThumbnail());
Expand Down
1 change: 1 addition & 0 deletions src/main/java/roomescape/domain/ReservationTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.time.LocalDate;
import java.time.LocalDateTime;

import java.time.LocalTime;

public class ReservationTime {
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/roomescape/domain/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package roomescape.domain;

public enum Role {
USER, ADMIN
}
1 change: 0 additions & 1 deletion src/main/java/roomescape/domain/Theme.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package roomescape.domain;

import roomescape.dto.theme.create.ThemeCreateRequest;
import roomescape.exception.ErrorCode;
import roomescape.exception.custom.InvalidInputException;

Expand Down
31 changes: 31 additions & 0 deletions src/main/java/roomescape/domain/User.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,55 @@
package roomescape.domain;

import roomescape.dto.reservation.create.ReservationCreateRequest;
import roomescape.exception.ErrorCode;
import roomescape.exception.custom.AuthorizationException;

import java.util.Optional;

public class User {

private Long id;
private String name;
private String email;
private String password;
private Role role;

public void checkPassword(String password) {
if (!this.password.equals(password)) {
throw new AuthorizationException(ErrorCode.UNAUTHORIZED_USER, "패스워드가 일치하지 않습니다. 다시 입력해주세요.");
}
}

public void checkUser() {
if(Optional.ofNullable(this).isEmpty()) {
throw new AuthorizationException(ErrorCode.UNAUTHORIZED_USER, "다시 로그인해주세요.");
}
}

public User(Long id) {
this.id = id;
}

public User(String name, String email, String password) {
this.name = name;
this.email = email;
this.password = password;
}

public User(String name, String email, String password, Role role) {
this.name = name;
this.email = email;
this.password = password;
this.role = role;
}

public User(long id, String name, String email, Role role) {
this.id = id;
this.name = name;
this.email = email;
this.role = role;
}

public Long getId() {
return id;
}
Expand All @@ -38,4 +66,7 @@ public String getPassword() {
return password;
}

public Role getRole() {
return role;
}
}
34 changes: 34 additions & 0 deletions src/main/java/roomescape/dto/auth/AuthUserResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package roomescape.dto.auth;

import roomescape.domain.Role;
import roomescape.domain.User;

public class AuthUserResponse {
private String name;
private String email;
private String password;
private Role role;

public AuthUserResponse(String name, String email, String password, Role role) {
this.name = name;
this.email = email;
this.password = password;
this.role = role;
}

public String getName() {
return name;
}

public String getEmail() {
return email;
}

public String getPassword() {
return password;
}

public Role getRole() {
return role;
}
}
Loading