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

[#43] Feat: 참여중인 방 여부 검사 기능 #44

Merged
merged 2 commits into from
May 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.sajang.devracebackend.controller;

import com.sajang.devracebackend.dto.problem.ProblemRequestDto;
import com.sajang.devracebackend.dto.room.RoomIdResponseDto;
import com.sajang.devracebackend.dto.problem.ProblemSaveRequestDto;
import com.sajang.devracebackend.dto.room.RoomSaveResponseDto;
import com.sajang.devracebackend.response.ResponseCode;
import com.sajang.devracebackend.response.ResponseData;
import com.sajang.devracebackend.service.RoomService;
Expand All @@ -25,8 +25,8 @@ public class RoomController {

@PostMapping("/rooms")
@Operation(summary = "방 생성 [jwt O]")
public ResponseEntity<ResponseData<RoomIdResponseDto>> createRoom(@RequestBody ProblemRequestDto problemRequestDto) throws IOException {
RoomIdResponseDto roomIdResponseDto = roomService.createRoom(problemRequestDto);
return ResponseData.toResponseEntity(ResponseCode.CREATED_ROOM, roomIdResponseDto);
public ResponseEntity<ResponseData<RoomSaveResponseDto>> createRoom(@RequestBody ProblemSaveRequestDto problemSaveRequestDto) throws IOException {
RoomSaveResponseDto roomSaveResponseDto = roomService.createRoom(problemSaveRequestDto);
return ResponseData.toResponseEntity(ResponseCode.CREATED_ROOM, roomSaveResponseDto);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sajang.devracebackend.controller;

import com.sajang.devracebackend.dto.user.SolvedResponseDto;
import com.sajang.devracebackend.dto.user.UserEnterResponseDto;
import com.sajang.devracebackend.dto.user.UserSolvedResponseDto;
import com.sajang.devracebackend.response.ResponseCode;
import com.sajang.devracebackend.response.ResponseData;
import com.sajang.devracebackend.service.UserService;
Expand All @@ -21,8 +22,15 @@ public class UserController {

@GetMapping("/users/solved-count")
@Operation(summary = "백준 solvedCount값 조회 [jwt O]")
public ResponseEntity<ResponseData<SolvedResponseDto>> checkUserSolvedCount() {
SolvedResponseDto solvedResponseDto = userService.checkUserSolvedCount();
return ResponseData.toResponseEntity(ResponseCode.READ_SOLVEDCOUNT, solvedResponseDto);
public ResponseEntity<ResponseData<UserSolvedResponseDto>> checkUserSolvedCount() {
UserSolvedResponseDto userSolvedResponseDto = userService.checkUserSolvedCount();
return ResponseData.toResponseEntity(ResponseCode.READ_SOLVEDCOUNT, userSolvedResponseDto);
}

@GetMapping("/users/rooms")
@Operation(summary = "참여중인 방 여부 검사 [jwt O]")
public ResponseEntity<ResponseData<UserEnterResponseDto>> findCurrentRoom() {
UserEnterResponseDto userEnterResponseDto = userService.findCurrentRoom();
return ResponseData.toResponseEntity(ResponseCode.READ_ROOM, userEnterResponseDto);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

@Getter
@NoArgsConstructor
public class ProblemRequestDto {
public class ProblemSaveRequestDto {

private Integer problemNumber; // 백준 문제 번호
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class RoomIdResponseDto {
public class RoomSaveResponseDto {

private Long roomId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.sajang.devracebackend.dto.user;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UserEnterResponseDto {

private Boolean isEnter; // 참여중인 방 존재 여부
private Long roomId; // null 가능.
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

@Getter
@NoArgsConstructor
public class SolvedResponseDto {
public class UserSolvedResponseDto {

private Integer solvedCount;

@Builder
public SolvedResponseDto(Integer solvedCount){
public UserSolvedResponseDto(Integer solvedCount){
this.solvedCount = solvedCount;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.sajang.devracebackend.service;

import com.sajang.devracebackend.dto.problem.ProblemRequestDto;
import com.sajang.devracebackend.dto.room.RoomIdResponseDto;
import com.sajang.devracebackend.dto.problem.ProblemSaveRequestDto;
import com.sajang.devracebackend.dto.room.RoomSaveResponseDto;

import java.io.IOException;

public interface RoomService {
RoomIdResponseDto createRoom(ProblemRequestDto problemRequestDto) throws IOException;
RoomSaveResponseDto createRoom(ProblemSaveRequestDto problemSaveRequestDto) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.sajang.devracebackend.service;

import com.sajang.devracebackend.domain.User;
import com.sajang.devracebackend.dto.user.SolvedResponseDto;
import com.sajang.devracebackend.dto.user.UserEnterResponseDto;
import com.sajang.devracebackend.dto.user.UserSolvedResponseDto;

public interface UserService {
User findUser(Long userId);
SolvedResponseDto checkUserSolvedCount();
User findLoginUser();
UserSolvedResponseDto checkUserSolvedCount();
UserEnterResponseDto findCurrentRoom();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import com.sajang.devracebackend.service.AuthService;
import com.sajang.devracebackend.service.AwsS3Service;
import com.sajang.devracebackend.service.UserService;
import com.sajang.devracebackend.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -44,13 +43,12 @@ public SignupResponseDto signup(MultipartFile imageFile, SignupRequestDto signup
}
UserServiceImpl.getSolvedCount(signupRequestDto.getBojId()); // solvedac 서버에 존재하지않는 백준id일경우 예외 처리.

Long loginUserId = SecurityUtil.getCurrentMemberId();
User user = userService.findUser(loginUserId);
User user = userService.findLoginUser();

// signup은 Role이 GUEST인 사용자만 이용가능한 API임.
if(!user.getRole().equals(Role.ROLE_GUEST) || user.getBojId() != null) {
// 이 로직을 SecurityConfig의 hasAuthority("ROLE_GUEST") 외에도 여기 또 써줘야하는 이유는,
// reissue로 인한 재발급 이후에도 이전 엑세스 토큰으로 '/signup' 경로에 다시 접근할 경우, 토큰 내의 권한은 GUEST이 맞겠지만 DB 내의 권한은 USER이기에 이러한 비정상적인 접근을 방지할 수 있기 때문임.
// reissue로 인한 재발급 이후에도 이전 엑세스 토큰으로 '/signup' 경로에 다시 접근할 경우, 토큰 내의 권한은 GUEST가 맞겠지만 DB 내의 권한은 USER이기에 이러한 비정상적인 접근을 방지할 수 있기 때문임.
throw new UserBadRequestException("이미 가입완료 되어있는 사용자입니다.");
}

Expand All @@ -69,7 +67,7 @@ else if(imageFile != null && signupRequestDto.getIsImageChange() == 0) { // 기
UserResponseDto userResponseDto = new UserResponseDto(user);

// 추가정보 입력후, 위에서 Role을 GUEST->USER로 업데이트했지만, 헤더의 jwt 토큰에 등록해둔 권한도 수정해야하기에, Access 토큰도 따로 재발급해야함.
TokenDto tokenDto = tokenProvider.generateAccessTokenByRefreshToken(loginUserId, Role.ROLE_USER, user.getRefreshToken());
TokenDto tokenDto = tokenProvider.generateAccessTokenByRefreshToken(user.getId(), Role.ROLE_USER, user.getRefreshToken());

return new SignupResponseDto(userResponseDto, tokenDto);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.sajang.devracebackend.domain.Problem;
import com.sajang.devracebackend.domain.Room;
import com.sajang.devracebackend.dto.problem.ProblemRequestDto;
import com.sajang.devracebackend.dto.room.RoomIdResponseDto;
import com.sajang.devracebackend.dto.problem.ProblemSaveRequestDto;
import com.sajang.devracebackend.dto.room.RoomSaveResponseDto;
import com.sajang.devracebackend.repository.ProblemRepository;
import com.sajang.devracebackend.repository.RoomRepository;
import com.sajang.devracebackend.service.ProblemService;
Expand All @@ -27,8 +27,8 @@ public class RoomServiceImpl implements RoomService {

@Transactional
@Override
public RoomIdResponseDto createRoom(ProblemRequestDto problemRequestDto) throws IOException {
Integer problemNumber = problemRequestDto.getProblemNumber();
public RoomSaveResponseDto createRoom(ProblemSaveRequestDto problemSaveRequestDto) throws IOException {
Integer problemNumber = problemSaveRequestDto.getProblemNumber();

Problem problem = problemRepository.findByNumber(problemNumber)
.orElse(null); // try~catch문 대신 null로 표현했음.
Expand All @@ -47,8 +47,8 @@ public RoomIdResponseDto createRoom(ProblemRequestDto problemRequestDto) throws
.problem(problem)
.build();
Long roomId = roomRepository.save(room).getId();
RoomIdResponseDto roomIdResponseDto = new RoomIdResponseDto(roomId);
RoomSaveResponseDto roomSaveResponseDto = new RoomSaveResponseDto(roomId);

return roomIdResponseDto;
return roomSaveResponseDto;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.sajang.devracebackend.service.impl;

import com.sajang.devracebackend.domain.User;
import com.sajang.devracebackend.dto.user.SolvedResponseDto;
import com.sajang.devracebackend.domain.mapping.UserRoom;
import com.sajang.devracebackend.dto.user.UserEnterResponseDto;
import com.sajang.devracebackend.dto.user.UserSolvedResponseDto;
import com.sajang.devracebackend.repository.UserRepository;
import com.sajang.devracebackend.response.exception.exception404.NoSuchBojIdException;
import com.sajang.devracebackend.response.exception.exception404.NoSuchUserException;
Expand All @@ -14,6 +16,8 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
Expand All @@ -30,19 +34,39 @@ public User findUser(Long userId) {

@Transactional(readOnly = true)
@Override
public SolvedResponseDto checkUserSolvedCount() {
public User findLoginUser() {
Long loginUserId = SecurityUtil.getCurrentMemberId();
User user = findUser(loginUserId);
SolvedResponseDto solvedResponseDto = getSolvedCount(user.getBojId());
User loginUser = findUser(loginUserId);
return loginUser;
}

@Transactional(readOnly = true)
@Override
public UserSolvedResponseDto checkUserSolvedCount() {
User user = findLoginUser();
UserSolvedResponseDto userSolvedResponseDto = getSolvedCount(user.getBojId());

return userSolvedResponseDto;
}

@Transactional(readOnly = true)
@Override
public UserEnterResponseDto findCurrentRoom() {
User user = findLoginUser();

Optional<UserRoom> optionalUserRoom = user.getUserRoomList().stream()
.filter(userRoom -> userRoom.getIsLeave() == 0) // getIsLeave() 값이 0인 경우만 필터링 (참여중인 방 찾기)
.findFirst();
UserRoom userRoom = optionalUserRoom.orElse(null);

return solvedResponseDto;
if(userRoom == null) return new UserEnterResponseDto(false, null); // 참여중인 방이 없음 X.
else return new UserEnterResponseDto(true, userRoom.getRoom().getId()); // 참여중인 방이 있음 O.
}


// ========== 유틸성 메소드 ========== //

@Transactional
public static SolvedResponseDto getSolvedCount(String bojId){ // WebClient로 외부 solved API 호출 메소드
public static UserSolvedResponseDto getSolvedCount(String bojId){ // WebClient로 외부 solved API 호출 메소드
try {
WebClient webClient = WebClient.builder()
.baseUrl("https://solved.ac/api/v3")
Expand All @@ -52,7 +76,7 @@ public static SolvedResponseDto getSolvedCount(String bojId){ // WebClient로
return webClient.get()
.uri("/user/show?handle=" + bojId)
.retrieve()
.bodyToMono(SolvedResponseDto.class)
.bodyToMono(UserSolvedResponseDto.class)
.block();
}catch (Exception e){
throw new NoSuchBojIdException("bojId = " + bojId); // solvedac 서버에 존재하지않는 백준id일경우 예외 처리.
Expand Down
Loading