Skip to content

Commit

Permalink
resolve : conflict 해결
Browse files Browse the repository at this point in the history
  • Loading branch information
EunChanNam committed Jan 15, 2024
2 parents 65dd124 + 2332c10 commit 63af2b9
Show file tree
Hide file tree
Showing 46 changed files with 774 additions and 192 deletions.
2 changes: 2 additions & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework:spring-tx:6.1.1'
testImplementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'

Expand Down
14 changes: 13 additions & 1 deletion api/src/main/java/dev/hooon/auth/AuthApiController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.hooon.auth;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -10,9 +11,10 @@
import dev.hooon.auth.application.AuthService;
import dev.hooon.auth.dto.TokenReIssueRequest;
import dev.hooon.auth.dto.request.AuthRequest;

import dev.hooon.auth.dto.response.AuthResponse;
import dev.hooon.auth.jwt.JwtAuthorization;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
Expand All @@ -37,6 +39,16 @@ public ResponseEntity<AuthResponse> login(
return ResponseEntity.ok(authResponse);
}

@PostMapping("/logout")
@Operation(summary = "로그아웃 API", description = "로그아웃을 한다")
@ApiResponse(responseCode = "200", useReturnTypeSchema = true)
public ResponseEntity<HttpStatus> logout(
@Parameter(hidden = true) @JwtAuthorization Long userId
) {
authService.logout(userId);
return ResponseEntity.ok(HttpStatus.OK);
}

@NoAuth
@PostMapping("/token")
@Operation(summary = "토큰 재발급 API", description = "토큰을 재발급한다")
Expand Down
39 changes: 39 additions & 0 deletions api/src/main/java/dev/hooon/booking/BookingApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dev.hooon.booking;

import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import dev.hooon.auth.jwt.JwtAuthorization;
import dev.hooon.booking.application.BookingService;
import dev.hooon.booking.dto.response.BookingListResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class BookingApiController {

private final BookingService bookingService;

@GetMapping("/api/users/booking")
@Operation(summary = "예매 조회 API", description = "예매를 조회한다")
@ApiResponse(responseCode = "200", useReturnTypeSchema = true)
public ResponseEntity<BookingListResponse> getBookings(
@Parameter(hidden = true) @JwtAuthorization Long userId,
@RequestParam(name = "duration") int duration,
@PageableDefault(size = 10) Pageable pageable
) {
BookingListResponse bookingListResponse = bookingService.getBookings(
userId,
duration,
pageable
);
return ResponseEntity.ok(bookingListResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public ResponseEntity<TicketBookingResponse> bookingTicket(
@Parameter(hidden = true) @JwtAuthorization Long userId,
@Valid @RequestBody TicketBookingRequest ticketBookingRequest
) {
TicketBookingResponse ticketBookingResponse = ticketBookingFacade.bookingTicket(userId, ticketBookingRequest);
TicketBookingResponse ticketBookingResponse = ticketBookingFacade.bookingTicket(
userId,
ticketBookingRequest.seatIds()
);
return ResponseEntity.ok(ticketBookingResponse);
}
}
23 changes: 19 additions & 4 deletions api/src/test/java/dev/hooon/auth/AuthApiControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,18 @@ class AuthApiControllerTest extends ApiTestSupport {
private UserService userService;
@Autowired
private AuthService authService;
private AuthRequest authRequest;

@BeforeEach
void setUp() {
UserJoinRequest userJoinRequest = new UserJoinRequest("user@example.com", "password123", "name123");
userService.join(userJoinRequest);
authRequest = new AuthRequest("user@example.com", "password123");
}

@Test
@DisplayName("[로그인 API를 호출하면 토큰이 응답된다]")
void loginTest() throws Exception {
// given
AuthRequest authRequest = new AuthRequest("user@example.com", "password123");

// when
ResultActions actions = mockMvc.perform(
post("/api/auth/login")
Expand All @@ -56,7 +55,6 @@ void loginTest() throws Exception {
@DisplayName("[토큰 재발급 API를 호출하면 새로운 엑세스 토큰이 응답된다]")
void reIssueAccessTokenTest() throws Exception {
// given
AuthRequest authRequest = new AuthRequest("user@example.com", "password123");
AuthResponse authResponse = authService.login(authRequest);
String refreshToken = authResponse.refreshToken();
TokenReIssueRequest tokenReIssueRequest = new TokenReIssueRequest(refreshToken);
Expand All @@ -72,4 +70,21 @@ void reIssueAccessTokenTest() throws Exception {
actions.andExpect(status().isOk())
.andExpect(content().string(not(emptyOrNullString())));
}

@Test
@DisplayName("[로그아웃 API를 호출하면 200 OK 응답이 반환된다]")
void logoutTest() throws Exception {
// given
AuthResponse authResponse = authService.login(authRequest);
String accessToken = authResponse.accessToken();

// when
ResultActions actions = mockMvc.perform(
post("/api/auth/logout")
.header("Authorization", accessToken)
);

// then
actions.andExpect(status().isOk());
}
}
98 changes: 98 additions & 0 deletions api/src/test/java/dev/hooon/booking/BookingApiControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package dev.hooon.booking;

import static org.springframework.http.HttpHeaders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import dev.hooon.common.support.ApiTestSupport;
import dev.hooon.user.domain.entity.User;

@DisplayName("[BookingApiController API 테스트]")
@Sql("/sql/user_bookings_find.sql")
class BookingApiControllerTest extends ApiTestSupport {

@Autowired
private MockMvc mockMvc;

@DisplayName("사용자는 조회 기간에 따른 예매 정보를 조회할 수 있다 - 1")
@Test
void getBookings_test_1() throws Exception {

// given
User user = new User();
ReflectionTestUtils.setField(user, "id", 1L);

// when
ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders
.get("/api/users/booking?duration=3600&page=0&size=2")
.header(AUTHORIZATION, accessToken)
);

// then
resultActions.andExpectAll(
status().isOk(),

jsonPath("$.bookingList.length()").value(2),

jsonPath("$.bookingList[0].bookingId").isNumber(),
jsonPath("$.bookingList[0].bookingDate").isString(),
jsonPath("$.bookingList[0].showInfo.showName").isString(),
jsonPath("$.bookingList[0].showInfo.showDate").isString(),
jsonPath("$.bookingList[0].showInfo.showRound").isNumber(),
jsonPath("$.bookingList[0].showInfo.showRoundStartTime").isString(),
jsonPath("$.bookingList[0].ticketNumber").isNumber(),
jsonPath("$.bookingList[0].currentState").isString(),

jsonPath("$.bookingList[1].bookingId").isNumber(),
jsonPath("$.bookingList[1].bookingDate").isString(),
jsonPath("$.bookingList[1].showInfo.showName").isString(),
jsonPath("$.bookingList[1].showInfo.showDate").isString(),
jsonPath("$.bookingList[1].showInfo.showRound").isNumber(),
jsonPath("$.bookingList[1].showInfo.showRoundStartTime").isString(),
jsonPath("$.bookingList[1].ticketNumber").isNumber(),
jsonPath("$.bookingList[1].currentState").isString()
);
}

@DisplayName("사용자는 조회 기간에 따른 예매 정보를 조회할 수 있다 - 2")
@Test
void getBookings_test_2() throws Exception {

// given
User user = new User();
ReflectionTestUtils.setField(user, "id", 1L);

// when
ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders
.get("/api/users/booking?duration=30&page=0&size=2")
.header(AUTHORIZATION, accessToken)
);

// then
resultActions.andExpectAll(
status().isOk(),

jsonPath("$.bookingList.length()").value(1),

jsonPath("$.bookingList[0].bookingId").isNumber(),
jsonPath("$.bookingList[0].bookingDate").isString(),
jsonPath("$.bookingList[0].showInfo.showName").isString(),
jsonPath("$.bookingList[0].showInfo.showDate").isString(),
jsonPath("$.bookingList[0].showInfo.showRound").isNumber(),
jsonPath("$.bookingList[0].showInfo.showRoundStartTime").isString(),
jsonPath("$.bookingList[0].ticketNumber").isNumber(),
jsonPath("$.bookingList[0].currentState").isString()

);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ private ResultActions doBooking() throws Exception {
@DisplayName("사용자는 예매한 티켓을 취소할 수 있다.")
@Test
void cancelBookingTest() throws Exception {

// given
User user = new User();
ReflectionTestUtils.setField(user, "id", 1L);
Expand Down
10 changes: 10 additions & 0 deletions api/src/test/java/dev/hooon/common/support/ApiTestSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import static org.springframework.http.MediaType.*;

import org.junit.jupiter.api.AfterEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
Expand Down Expand Up @@ -38,6 +40,14 @@ protected String toJson(Object object) throws JsonProcessingException {
return objectMapper.writeValueAsString(object);
}

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@AfterEach
public void cleanRedis() {
redisTemplate.delete(redisTemplate.keys("*"));
}

@PostConstruct
public void setUpUser() throws Exception {
// 캐싱해서 단 한번만 호출
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import dev.hooon.booking.domain.entity.Booking;
import dev.hooon.booking.domain.entity.Ticket;
import dev.hooon.booking.domain.repository.BookingRepository;
import dev.hooon.common.fixture.SeatFixture;
import dev.hooon.common.fixture.TestFixture;
Expand Down Expand Up @@ -54,8 +53,7 @@ void getShowRanking_test() throws Exception {
Seat seat = SeatFixture.getSeat(show);
seatRepository.saveAll(List.of(seat));

Booking booking = Booking.of(user, show);
booking.addTicket(Ticket.of(seat));
Booking booking = Booking.of(user, show, List.of(seat));
bookingRepository.save(booking);

//when
Expand Down
23 changes: 21 additions & 2 deletions core/src/main/java/dev/hooon/auth/application/AuthService.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

package dev.hooon.auth.application;

import static dev.hooon.auth.exception.AuthErrorCode.*;
Expand All @@ -9,10 +8,13 @@
import org.springframework.transaction.annotation.Transactional;

import dev.hooon.auth.domain.entity.Auth;
import dev.hooon.auth.domain.entity.BlacklistToken;
import dev.hooon.auth.domain.repository.AuthRepository;
import dev.hooon.auth.domain.repository.BlacklistRepository;
import dev.hooon.auth.dto.request.AuthRequest;
import dev.hooon.auth.dto.response.AuthResponse;
import dev.hooon.auth.entity.EncryptHelper;
import dev.hooon.auth.exception.AuthException;
import dev.hooon.common.exception.NotFoundException;
import dev.hooon.user.application.UserService;
import lombok.RequiredArgsConstructor;
Expand All @@ -25,6 +27,7 @@ public class AuthService {
private final JwtProvider jwtProvider;
private final AuthRepository authRepository;
private final EncryptHelper encryptHelper;
private final BlacklistRepository blacklistRepository;

private Auth getAuthByRefreshToken(String refreshToken) {
return authRepository.findByRefreshToken(refreshToken)
Expand All @@ -37,7 +40,7 @@ private AuthResponse saveAuth(Long userId) {
Optional<Auth> auth = authRepository.findByUserId(userId);

auth.ifPresentOrElse(
(none) -> authRepository.updateRefreshToken(auth.get().getId(), refreshToken),
existingAuth -> authRepository.updateRefreshToken(existingAuth.getId(), refreshToken),
() -> {
Auth newAuth = Auth.of(userId, refreshToken);
authRepository.save(newAuth);
Expand All @@ -60,7 +63,23 @@ public AuthResponse login(AuthRequest authRequest) {
throw new NotFoundException(FAILED_LOGIN_BY_ANYTHING);
}

@Transactional
public void logout(Long userId) {
authRepository.findByUserId(userId).ifPresentOrElse(
auth ->
blacklistRepository.save(BlacklistToken.of(auth.getRefreshToken())),
() -> {
throw new NotFoundException(NOT_FOUND_USER_ID);
}
);
}

public String createAccessTokenByRefreshToken(String refreshToken) {
boolean isBlacklisted = blacklistRepository.existsByRefreshToken(refreshToken);
if (isBlacklisted) {
throw new AuthException(BLACKLISTED_TOKEN);
}

Auth auth = getAuthByRefreshToken(refreshToken);
Long userId = userService.getUserById(auth.getUserId()).getId();
return jwtProvider.createAccessToken(userId);
Expand Down
7 changes: 2 additions & 5 deletions core/src/main/java/dev/hooon/auth/domain/entity/Auth.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package dev.hooon.auth.domain.entity;

import static dev.hooon.common.exception.CommonValidationError.*;
import static jakarta.persistence.GenerationType.*;

import org.springframework.util.Assert;

import dev.hooon.user.domain.entity.UserRole;
import dev.hooon.common.entity.TimeBaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
Expand All @@ -18,7 +15,7 @@
@Getter
@NoArgsConstructor
@Table(name = "auth_table")
public class Auth {
public class Auth extends TimeBaseEntity {

@Id
@GeneratedValue(strategy = IDENTITY)
Expand Down
Loading

0 comments on commit 63af2b9

Please sign in to comment.