Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…dangkong into refactor/#369
  • Loading branch information
jhon3242 committed Oct 24, 2024
2 parents 0ad53ce + e11b555 commit cb56593
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 65 deletions.
12 changes: 6 additions & 6 deletions backend/src/docs/asciidoc/room.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,27 @@ include::{snippets}/room/join/response-cookies.adoc[]

'''

=== 방 재참여
=== 사용자 정보 조회

==== curl

include::{snippets}/room/rejoin/curl-request.adoc[]
include::{snippets}/room/member/curl-request.adoc[]

==== request

include::{snippets}/room/rejoin/http-request.adoc[]
include::{snippets}/room/member/http-request.adoc[]

request cookies

include::{snippets}/room/rejoin/request-cookies.adoc[]
include::{snippets}/room/member/request-cookies.adoc[]

==== response

include::{snippets}/room/rejoin/http-response.adoc[]
include::{snippets}/room/member/http-response.adoc[]

response fields

include::{snippets}/room/join/response-fields.adoc[]
include::{snippets}/room/member/response-fields.adoc[]

'''

Expand Down
7 changes: 4 additions & 3 deletions backend/src/main/java/ddangkong/config/CorsConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@
@Configuration
public class CorsConfig implements WebMvcConfigurer {

private final String corsOrigin;
private final String[] corsOrigin;

public CorsConfig(@Value("${cors.origin}") String corsOrigin) {
public CorsConfig(@Value("${cors.origin}") String[] corsOrigin) {
this.corsOrigin = corsOrigin;
}

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(corsOrigin)
.allowedOriginPatterns(corsOrigin)
.allowedMethods(
HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PATCH.name(), HttpMethod.DELETE.name()
)
.allowCredentials(true)
.allowedHeaders("*");
}
}

This file was deleted.

33 changes: 21 additions & 12 deletions backend/src/main/java/ddangkong/controller/room/RoomController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@
import ddangkong.facade.room.dto.RoomInfoResponse;
import ddangkong.facade.room.dto.RoomJoinRequest;
import ddangkong.facade.room.dto.RoomJoinResponse;
import ddangkong.facade.room.dto.RoomMemberResponse;
import ddangkong.facade.room.dto.RoomSettingRequest;
import ddangkong.facade.room.dto.RoomStatusResponse;
import ddangkong.facade.room.dto.RoundFinishedResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand All @@ -36,19 +39,21 @@
public class RoomController {

private final RoomFacade roomFacade;
private final RejoinCookieEncryptor rejoinCookieEncryptor;
private final RoomMemberCookieEncryptor roomMemberCookieEncryptor;

@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/balances/rooms")
public RoomJoinResponse createRoom(@Valid @RequestBody RoomJoinRequest request, HttpServletResponse response) {
public RoomJoinResponse createRoom(@Valid @RequestBody RoomJoinRequest request,
HttpServletRequest httpRequest,
HttpServletResponse httpResponse) {
RoomJoinResponse roomJoinResponse = roomFacade.createRoom(request.nickname());
setEncryptCookie(response, roomJoinResponse.member().memberId());
setEncryptCookie(httpRequest, httpResponse, roomJoinResponse.member().memberId());
return roomJoinResponse;
}

@GetMapping("/balances/rooms/rejoin")
public RoomJoinResponse rejoinRoom(@CookieValue(name = "${cookie.rejoin-key}") String cookieValue) {
return roomFacade.rejoinRoom(rejoinCookieEncryptor.getDecodedCookieValue(cookieValue));
@GetMapping("/balances/rooms/member")
public RoomMemberResponse getRoomMemberInfo(@CookieValue(name = "${cookie.rejoin-key}") String cookieValue) {
return roomFacade.getRoomMemberInfo(roomMemberCookieEncryptor.getDecodedCookieValue(cookieValue));
}

@Polling
Expand All @@ -68,9 +73,10 @@ public void updateRoomSetting(@PathVariable @Positive Long roomId,
@PostMapping("/balances/rooms/{uuid}/members")
public RoomJoinResponse joinRoom(@PathVariable String uuid,
@Valid @RequestBody RoomJoinRequest request,
HttpServletResponse response) {
HttpServletRequest httpRequest,
HttpServletResponse httpResponse) {
RoomJoinResponse roomJoinResponse = roomFacade.joinRoom(request.nickname(), uuid);
setEncryptCookie(response, roomJoinResponse.member().memberId());
setEncryptCookie(httpRequest, httpResponse, roomJoinResponse.member().memberId());
return roomJoinResponse;
}

Expand Down Expand Up @@ -117,8 +123,11 @@ public InitialRoomResponse isInitialRoom(@PathVariable @Positive Long roomId) {
return roomFacade.isInitialRoom(roomId);
}

private void setEncryptCookie(HttpServletResponse response, Object cookieValue) {
Cookie encodedCookie = rejoinCookieEncryptor.getEncodedCookie(cookieValue);
response.addCookie(encodedCookie);
private void setEncryptCookie(HttpServletRequest request,
HttpServletResponse response,
Object cookieValue) {
String origin = request.getHeader(HttpHeaders.ORIGIN);
ResponseCookie encodedCookie = roomMemberCookieEncryptor.getEncodedCookie(cookieValue, origin);
response.addHeader(HttpHeaders.SET_COOKIE, encodedCookie.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ddangkong.controller.room;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.server.Cookie.SameSite;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;

@Component
public class RoomMemberCookieEncryptor {

private static final String DEFAULT_PATH = "/api/balances/rooms";
private static final String LOCALHOST = "http://localhost";

private final EncryptionUtils encryptionUtils;

private final String rejoinKey;

public RoomMemberCookieEncryptor(EncryptionUtils encryptionUtils, @Value("${cookie.rejoin-key}") String rejoinKey) {
this.encryptionUtils = encryptionUtils;
this.rejoinKey = rejoinKey;
}

public ResponseCookie getEncodedCookie(Object value, String origin) {
String encrypt = encryptionUtils.encrypt(String.valueOf(value));
return ResponseCookie.from(rejoinKey, encrypt)
.httpOnly(true)
.secure(true)
.path(DEFAULT_PATH)
.sameSite(getSameSiteOption(origin))
.build();
}

private String getSameSiteOption(String origin) {
if (origin != null && origin.startsWith(LOCALHOST)) {
return SameSite.NONE.attributeValue();
}
return SameSite.LAX.attributeValue();
}

public Long getDecodedCookieValue(String cookieValue) {
return Long.parseLong(encryptionUtils.decrypt(cookieValue));
}
}
5 changes: 3 additions & 2 deletions backend/src/main/java/ddangkong/facade/room/RoomFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import ddangkong.facade.room.dto.InitialRoomResponse;
import ddangkong.facade.room.dto.RoomInfoResponse;
import ddangkong.facade.room.dto.RoomJoinResponse;
import ddangkong.facade.room.dto.RoomMemberResponse;
import ddangkong.facade.room.dto.RoomSettingRequest;
import ddangkong.facade.room.dto.RoomStatusResponse;
import ddangkong.facade.room.dto.RoundFinishedResponse;
Expand Down Expand Up @@ -53,10 +54,10 @@ public RoomJoinResponse joinRoom(String nickname, String uuid) {
}

@Transactional(readOnly = true)
public RoomJoinResponse rejoinRoom(Long memberId) {
public RoomMemberResponse getRoomMemberInfo(Long memberId) {
Member member = memberService.getMemberById(memberId);
Room room = member.getRoom();
return new RoomJoinResponse(room.getId(), room.getUuid(), new MemberResponse(member));
return new RoomMemberResponse(room.getId(), room.getUuid(), new MemberResponse(member));
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ddangkong.facade.room.dto;

import ddangkong.facade.room.member.dto.MemberResponse;

public record RoomMemberResponse(
Long roomId,
String roomUuid,
MemberResponse member
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ class 쿠키 {
}

@Test
void 쿠키를_통해_방에_재참여_할_수_있다() {
void 쿠키를_통해_사용자_정보를_조회_할_수_있다() {
// given
RoomJoinRequest body = new RoomJoinRequest("참가자");
String cookie = RestAssured.given().log().all()
Expand All @@ -362,7 +362,7 @@ class 쿠키 {
RoomJoinResponse roomJoinResponse = RestAssured.given().log().all()
.contentType(ContentType.JSON)
.cookie("test_cookie", cookie)
.when().get("/api/balances/rooms/rejoin")
.when().get("/api/balances/rooms/member")
.then().contentType(ContentType.JSON).log().all()
.statusCode(200)
.extract().as(RoomJoinResponse.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ddangkong.controller.room;

import static org.assertj.core.api.Assertions.assertThat;

import ddangkong.controller.BaseControllerTest;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseCookie;

class RoomMemberCookieEncryptorTest extends BaseControllerTest {

@Autowired
private RoomMemberCookieEncryptor roomMemberCookieEncryptor;

@Nested
class 방_멤버_쿠키_암호화 {

@Test
void 로컬_환경인_경우_SameSite는_None_이다() {
// given
String value = "ThisIsMySecretKe";
String origin = "http://localhost:3306/api";

// when
ResponseCookie encodedCookie = roomMemberCookieEncryptor.getEncodedCookie(value, origin);

// then
assertThat(encodedCookie.getSameSite()).isEqualTo("None");
}

@Test
void 로컬_환경이_아닌_경우_SameSite는_Lax_이다() {
// given
String value = "ThisIsMySecretKe";
String origin = "ddangkong.kr";

// when
ResponseCookie encodedCookie = roomMemberCookieEncryptor.getEncodedCookie(value, origin);

// then
assertThat(encodedCookie.getSameSite()).isEqualTo("Lax");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import static org.springframework.restdocs.request.RequestDocumentation.queryParameters;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import ddangkong.controller.room.RejoinCookieEncryptor;
import ddangkong.controller.room.RoomMemberCookieEncryptor;
import ddangkong.controller.room.EncryptionUtils;
import ddangkong.controller.room.RoomController;
import ddangkong.documentation.BaseDocumentationTest;
Expand All @@ -37,6 +37,7 @@
import ddangkong.facade.room.dto.RoomInfoResponse;
import ddangkong.facade.room.dto.RoomJoinRequest;
import ddangkong.facade.room.dto.RoomJoinResponse;
import ddangkong.facade.room.dto.RoomMemberResponse;
import ddangkong.facade.room.dto.RoomSettingRequest;
import ddangkong.facade.room.dto.RoomSettingResponse;
import ddangkong.facade.room.dto.RoomStatusResponse;
Expand All @@ -53,7 +54,7 @@
import org.springframework.http.MediaType;

@WebMvcTest(value = RoomController.class)
@Import(value = {RejoinCookieEncryptor.class, EncryptionUtils.class})
@Import(value = {RoomMemberCookieEncryptor.class, EncryptionUtils.class})
class RoomDocumentationTest extends BaseDocumentationTest {

@MockBean
Expand Down Expand Up @@ -218,24 +219,24 @@ class 방_참여 {
}

@Nested
class 방_재참여 {
class 사용자_정보_조회 {

private static final String ENDPOINT = "/api/balances/rooms/rejoin";
private static final String ENDPOINT = "/api/balances/rooms/member";

@Test
void 방에_재참여하여_유저_정보를_조회한다() throws Exception {
void 사용자_정보를_조회한다() throws Exception {
// given
RoomJoinResponse response = new RoomJoinResponse(1L, "488fd79f92a34131bf2a628bd58c5d2c",
RoomMemberResponse response = new RoomMemberResponse(1L, "488fd79f92a34131bf2a628bd58c5d2c",
new MemberResponse(2L, "타콩", false));
when(roomFacade.rejoinRoom(anyLong())).thenReturn(response);
when(roomFacade.getRoomMemberInfo(anyLong())).thenReturn(response);

//when & then
mockMvc.perform(get(ENDPOINT)
.contentType(MediaType.APPLICATION_JSON)
.cookie(new Cookie("test_cookie", "oNnHwjSR1G4E5L8Mute61w=="))
)
.andExpect(status().isOk())
.andDo(document("room/rejoin",
.andDo(document("room/member",
requestCookies(
cookieWithName("test_cookie").description("사용자 인증에 필요한 쿠키(쿠키의 키 값은 UUID로 예측할 수 없는 값이 들어감)")
),
Expand Down
Loading

0 comments on commit cb56593

Please sign in to comment.