Skip to content

Commit

Permalink
Merge pull request #103 from KUIT-Space/develop
Browse files Browse the repository at this point in the history
24.08.14 배포
  • Loading branch information
seongjunnoh authored Aug 14, 2024
2 parents 8983a5b + 7b4c0c2 commit 868cb9b
Show file tree
Hide file tree
Showing 36 changed files with 354 additions and 217 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies {
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // JPA 스타터 추가
runtimeOnly 'com.h2database:h2' // test용 db인 h2Database 추가
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0' // p6spy 설정 추가
// implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0' // p6spy 설정 추가
implementation 'org.springframework.boot:spring-boot-starter-validation' // validation 추가
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-websocket' // webSocket 추가
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
public enum UserSpaceValidationInterceptorURL {
//SPACE("/space/**"),
TEST("/space/{spaceId}/test/**"),
VOICEROOM("/space/{spaceId}/voiceRoom/**")
;

private final String urlPattern;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/space/space_spring/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void addCorsMappings(CorsRegistry registry) {
"http://localhost:5173/KUIT-Space-Front/", "https://localhost:5173/KUIT-Space-Front/",
"https://kuit-space.github.io/KUIT-Space-front/")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.exposedHeaders("location")
.exposedHeaders("location", "Authorization")
.allowedHeaders("*")
.allowCredentials(true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package space.space_spring.config.filter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;

import java.io.IOException;
@Component
public class RequestCachingFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
filterChain.doFilter(wrappedRequest, response);
}
}
56 changes: 56 additions & 0 deletions src/main/java/space/space_spring/controller/LikeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package space.space_spring.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.response.BaseResponse;
import space.space_spring.service.LikeService;

@RestController
@RequiredArgsConstructor
@RequestMapping("/space/{spaceId}/board/post/{postId}")
@Slf4j
public class LikeController {

private final LikeService likeService;

// 게시글 좋아요
@PostMapping("/like")
public BaseResponse<String> likePost(
@JwtLoginAuth Long userId,
@PathVariable Long spaceId,
@PathVariable Long postId
) {
// TODO 1: 유저가 스페이스에 속하는지 검증
likeService.validateUserInSpace(userId, spaceId);

// TODO 2: 유저가 해당 게시글에 이미 좋아요를 눌렀는지 검증
likeService.validateAlreadyLiked(userId, postId);

// TODO 3: 좋아요 로직 수행
likeService.likePost(userId, postId);

return new BaseResponse<>("게시글에 좋아요를 눌렀습니다.");
}


// 게시글 좋아요 취소
@DeleteMapping("/like")
public BaseResponse<String> unlikePost(
@JwtLoginAuth Long userId,
@PathVariable Long spaceId,
@PathVariable Long postId
) {
// TODO 1: 유저가 스페이스에 속하는지 검증
likeService.validateUserInSpace(userId, spaceId);

// TODO 2: 유저가 해당 게시글에 좋아요를 눌렀는지 검증
likeService.validateNotLikedYet(userId, postId);

// TODO 3: 좋아요 취소 로직 수행
likeService.unlikePost(userId, postId);

return new BaseResponse<>("게시글에 좋아요를 취소하였습니다.");
}
}
18 changes: 8 additions & 10 deletions src/main/java/space/space_spring/controller/SpaceController.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.space.GetSpaceJoinDto;
import space.space_spring.dto.space.PostSpaceJoinDto;
import space.space_spring.dto.space.request.PostSpaceCreateDto;
import space.space_spring.dto.space.response.GetUserInfoBySpaceResponse;
import space.space_spring.dto.space.request.PostSpaceCreateRequest;

import space.space_spring.dto.userSpace.GetUserProfileInSpaceDto;
import space.space_spring.dto.userSpace.PutUserProfileInSpaceDto;
import space.space_spring.entity.UserSpace;
import space.space_spring.entity.Space;
import space.space_spring.exception.CustomException;
import space.space_spring.exception.MultipartFileException;
import space.space_spring.exception.SpaceException;
import space.space_spring.response.BaseResponse;
import space.space_spring.service.S3Uploader;
import space.space_spring.service.SpaceService;
Expand All @@ -42,18 +40,18 @@ public class SpaceController {
private final UserSpaceUtils userSpaceUtils;

@PostMapping("")
public BaseResponse<String> createSpace(@JwtLoginAuth Long userId, @Validated @ModelAttribute PostSpaceCreateRequest postSpaceCreateRequest, BindingResult bindingResult) throws IOException {
public BaseResponse<PostSpaceCreateDto.Response> createSpace(@JwtLoginAuth Long userId, @Validated @ModelAttribute PostSpaceCreateDto.Request postSpaceCreateRequest, BindingResult bindingResult) throws IOException {
if (bindingResult.hasErrors()) {
throw new SpaceException(INVALID_SPACE_CREATE, getErrorMessage(bindingResult));
throw new CustomException(INVALID_SPACE_CREATE, getErrorMessage(bindingResult));
}

// TODO 1. 스페이스 썸네일을 s3에 upload
String spaceImgUrl = processSpaceImage(postSpaceCreateRequest.getSpaceProfileImg());

// TODO 2. s3에 저장하고 받은 이미지 url 정보와 spaceName 정보로 space create 작업 수행
spaceService.createSpace(userId, postSpaceCreateRequest.getSpaceName(), spaceImgUrl);
Space createSpace = spaceService.createSpace(userId, postSpaceCreateRequest.getSpaceName(), spaceImgUrl);

return new BaseResponse<>("스페이스 생성 성공");
return new BaseResponse<>(new PostSpaceCreateDto.Response(createSpace.getSpaceId()));
}

private String processSpaceImage(MultipartFile spaceProfileImg) throws IOException {
Expand All @@ -67,7 +65,7 @@ private String processSpaceImage(MultipartFile spaceProfileImg) throws IOExcepti

private void validateImageFile(MultipartFile spaceProfileImg) {
if (!s3Uploader.isFileImage(spaceProfileImg)) {
throw new MultipartFileException(IS_NOT_IMAGE_FILE);
throw new CustomException(IS_NOT_IMAGE_FILE);
}
}

Expand Down Expand Up @@ -133,7 +131,7 @@ private void validateIsUserInSpace(Long userId, Long spaceId) {
@PutMapping("/{spaceId}/member-profile")
public BaseResponse<PutUserProfileInSpaceDto.Response> updateUserProfileInSpace(@JwtLoginAuth Long userId, @PathVariable Long spaceId, @Validated @ModelAttribute PutUserProfileInSpaceDto.Request request, BindingResult bindingResult) throws IOException {
if (bindingResult.hasErrors()) {
throw new SpaceException(INVALID_USER_SPACE_PROFILE, getErrorMessage(bindingResult));
throw new CustomException(INVALID_USER_SPACE_PROFILE, getErrorMessage(bindingResult));
}

// TODO 1. 유저가 스페이스에 가입되어 있는지 검증
Expand Down
11 changes: 6 additions & 5 deletions src/main/java/space/space_spring/controller/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
Expand All @@ -11,11 +12,13 @@
import space.space_spring.dto.user.request.PostUserLoginRequest;
import space.space_spring.dto.user.request.PostUserSignupRequest;
import space.space_spring.dto.user.response.GetSpaceInfoForUserResponse;
import space.space_spring.exception.UserException;
import space.space_spring.exception.CustomException;
import space.space_spring.response.BaseResponse;
import space.space_spring.service.UserService;
import space.space_spring.util.userSpace.UserSpaceUtils;

import java.util.stream.Collectors;

import static space.space_spring.response.status.BaseExceptionResponseStatus.*;
import static space.space_spring.util.bindingResult.BindingResultUtils.getErrorMessage;

Expand All @@ -34,7 +37,7 @@ public class UserController {
@PostMapping("/signup")
public BaseResponse<String> signup(@Validated @RequestBody PostUserSignupRequest postUserSignupRequest, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
throw new UserException(INVALID_USER_SIGNUP, getErrorMessage(bindingResult));
throw new CustomException(INVALID_USER_SIGNUP, getErrorMessage(bindingResult));
}

userService.signup(postUserSignupRequest);
Expand All @@ -48,7 +51,7 @@ public BaseResponse<String> signup(@Validated @RequestBody PostUserSignupRequest
@PostMapping("/login")
public BaseResponse<String> login(@Validated @RequestBody PostUserLoginRequest postUserLoginRequest, BindingResult bindingResult, HttpServletResponse response) {
if (bindingResult.hasErrors()) {
throw new UserException(INVALID_USER_LOGIN, getErrorMessage(bindingResult));
throw new CustomException(INVALID_USER_LOGIN, getErrorMessage(bindingResult));
}

String jwtLogin = userService.login(postUserLoginRequest);
Expand All @@ -75,8 +78,6 @@ public BaseResponse<GetSpaceInfoForUserResponse> showUserSpaceList(@JwtLoginAuth
@GetMapping("/profile")
public BaseResponse<GetUserProfileListDto.Response> showUserProfileList(@JwtLoginAuth Long userId) {

log.info("userId = {}", userId);

return new BaseResponse<>(userService.getUserProfileList(userId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.userSpace.UserSpaceAuth;
import space.space_spring.dao.UserSpaceDao;
import space.space_spring.dao.VoiceRoomRepository;
import space.space_spring.dto.VoiceRoom.*;
import space.space_spring.entity.Space;
import space.space_spring.entity.User;
import space.space_spring.entity.UserSpace;
import space.space_spring.exception.VoiceRoomException;

import space.space_spring.exception.CustomException;
import space.space_spring.response.BaseResponse;
import space.space_spring.service.LiveKitService;
import space.space_spring.service.VoiceRoomService;
Expand Down Expand Up @@ -47,15 +46,15 @@ public BaseResponse<PostVoiceRoomDto.Response> createRoom(
@PathVariable("spaceId") @NotNull long spaceId,
@JwtLoginAuth Long userId,
@Validated @RequestBody PostVoiceRoomDto.Request voiceRoomRequest,
@UserSpaceAuth String userSpaceAuth,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
throw new VoiceRoomException(INVALID_VOICEROOM_REQUEST,getErrorMessage(bindingResult));
throw new CustomException(INVALID_VOICEROOM_REQUEST,getErrorMessage(bindingResult));
}

//해당 유저가 voice이 있는 space에 포함되어 있는지(권한이 있는지) 확인
validateIsUserInSpace(spaceId,userId);
//해당 유저가 현재 space에 대해 관리자 권한을 갖고 있는지 확인
validateManagerPermission(spaceId,userId);
validateManagerPermission(userSpaceAuth);

//Todo response 내용을 무엇을 주면 좋을지 ( POST response 전체 기능 통일 하는 것일 좋아보임 )
PostVoiceRoomDto.Response res = new PostVoiceRoomDto.Response(voiceRoomService.createVoiceRoom(spaceId,voiceRoomRequest));
return new BaseResponse<>(res);
Expand All @@ -72,8 +71,6 @@ public BaseResponse<GetVoiceRoomList.Response> getRoomList(

boolean showParticipantValue = (showParticipant != null) ? showParticipant : false;

//해당 유저가, voiceRoom이 있는 space에 포함되어 있는지(권한이 있는지) 확인
validateIsUserInSpace(spaceId,userId);

GetVoiceRoomList.Request voiceRoomList=new GetVoiceRoomList.Request(limit, showParticipant);

Expand All @@ -89,8 +86,7 @@ public BaseResponse<String> getToken(
@PathVariable("voiceRoomId") @NotNull Long roomId,
HttpServletResponse response
){
//해당 유저가, voiceRoom이 있는 space에 포함되어 있는지(권한이 있는지) 확인
validateIsUserInSpace(spaceId,userId);

//해당 voiceRoomId가 존재하는지 확인
validateVoiceRoom(roomId);
//해당 voiceRoom이 해당 space에 속한것이 맞는지 확인
Expand All @@ -109,8 +105,7 @@ public BaseResponse<GetParticipantList.Response> getParticipants(
@JwtLoginAuth Long userId,
@PathVariable("voiceRoomId") @NotNull Long roomId
){
//해당 유저가 voice이 있는 space에 포함되어 있는지(권한이 있는지) 확인
validateIsUserInSpace(spaceId,userId);

//해당 voiceRoomId가 존재하는지 확인
validateVoiceRoom(roomId);
//해당 voiceRoom이 해당 space에 속한것이 맞는지 확인
Expand All @@ -125,16 +120,15 @@ public BaseResponse<String> updateVoiceRoom(
@PathVariable("spaceId") @NotNull long spaceId,
@JwtLoginAuth Long userId,
@Validated @RequestBody PatchVoiceRoom patchVoiceRoom,
@UserSpaceAuth String userSpaceAuth,
BindingResult bindingResult
){

if(bindingResult.hasErrors()){
throw new VoiceRoomException(INVALID_VOICEROOM_REQUEST,getErrorMessage(bindingResult));
throw new CustomException(INVALID_VOICEROOM_REQUEST,getErrorMessage(bindingResult));
}
//해당 유저가 voice이 있는 space에 포함되어 있는지(권한이 있는지) 확인
validateIsUserInSpace(spaceId,userId);
//해당 유저가 현재 space에 대해 관리자 권한을 갖고 있는지 확인
validateManagerPermission(spaceId,userId);
validateManagerPermission(userSpaceAuth);
//해당 voiceRoom이 해당 space에 속한것이 맞는지 확인
for(PatchVoiceRoom.UpdateRoom updateRoom : patchVoiceRoom.getUpdateRoomList()) {
validateVoiceRoomInSpace(spaceId, updateRoom.getRoomId());
Expand All @@ -149,12 +143,12 @@ public BaseResponse<String> updateVoiceRoom(
public BaseResponse<String> deleteVoiceRoom(
@PathVariable("spaceId") @NotNull long spaceId,
@JwtLoginAuth Long userId,
@PathVariable("voiceRoomId") @NotNull Long voiceRoomId
@PathVariable("voiceRoomId") @NotNull Long voiceRoomId,
@UserSpaceAuth String userSpaceAuth
){
//해당 유저가 voice이 있는 space에 포함되어 있는지(권한이 있는지) 확인
validateIsUserInSpace(spaceId,userId);

//해당 유저가 현재 space에 대해 관리자 권한을 갖고 있는지 확인
validateManagerPermission(spaceId,userId);
validateManagerPermission(userSpaceAuth);
//해당 voiceRoom이 해당 space에 속한것이 맞는지 확인
validateVoiceRoomInSpace(spaceId, voiceRoomId);

Expand All @@ -169,43 +163,29 @@ public BaseResponse<String> postRoomStatus(){
return new BaseResponse<String>(null);
}

private void validateIsUserInSpace( Long spaceId,Long userId) {
// 유저가 스페이스에 속할 경우 exception이 터지지 않을 것임
// 그렇지 않을 경우, USER_IS_NOT_IN_SPACE 예외가 터질 것임 -> 추후 exception handling 과정 필요

//현재는 스페이스 접근 권한을 일괄적으로 예외 처리
//분리 가능성 및 효용성 검토 필요
userSpaceUtils.isUserInSpace(userId, spaceId);
}
private boolean validateVoiceRoom(long voiceRoomId){
//Todo 해당 보이스룸이 존재하는지 확인
if(!voiceRoomRepository.existsByVoiceRoomId(voiceRoomId)){
throw new VoiceRoomException(VOICEROOM_NOT_EXIST);
throw new CustomException(VOICEROOM_NOT_EXIST);
}
return true;
}
private boolean validateVoiceRoomNameExist(String voiceRoomName){
if(!voiceRoomRepository.existsByName(voiceRoomName)){
throw new VoiceRoomException(VOICEROOM_NAME_ALREADY_EXIST);
throw new CustomException(VOICEROOM_NAME_ALREADY_EXIST);
}
return true;
}
private boolean validateVoiceRoomInSpace(long spaceId,long voiceRoomId){
if(! (voiceRoomRepository.findById(voiceRoomId).getSpace().getSpaceId().equals(spaceId))){
throw new VoiceRoomException(VOICEROOM_NOT_IN_SPACE);
throw new CustomException(VOICEROOM_NOT_IN_SPACE);
}
return true;
}
private boolean validateManagerPermission(long spaceId,long userId){
private boolean validateManagerPermission(String userSpaceAuth){
//해당 유저가 현재 space에 대해 관리자 권한을 갖고 있는지 확인
//TODO 권한 확인 과정을 일괄적으로 처리 할 수 있는 코드가 필요해 보임
User user = userUtils.findUserByUserId(userId);
Space space = spaceUtils.findSpaceBySpaceId(spaceId);
//이미 userSpace 존재 여부를 검사해서 null 검사는 생략함

if(!userSpaceDao.findUserSpaceByUserAndSpace(user,space).get().getUserSpaceAuth().toString().equals(MANAGER.getAuth())){
System.out.print("Author :" +userSpaceDao.findUserSpaceByUserAndSpace(user,space).get().getUserSpaceAuth().toString());
throw new VoiceRoomException(VOICEROOM_DO_NOT_HAVE_PERMISSION);
if(!userSpaceAuth.equals(MANAGER.getAuth())){
throw new CustomException(VOICEROOM_DO_NOT_HAVE_PERMISSION);
}
return true;
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/space/space_spring/dao/LikeDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package space.space_spring.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import space.space_spring.entity.Post;
import space.space_spring.entity.PostLike;
import space.space_spring.entity.User;

import java.util.Optional;

public interface LikeDao extends JpaRepository<PostLike, Long> {
Optional<PostLike> findByUserAndPost(User user, Post post);
}
5 changes: 3 additions & 2 deletions src/main/java/space/space_spring/dao/UserDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ public boolean hasDuplicateEmail(String email, UserSignupType signupType) {
return count > 0;
}

public User getUserByEmail(String email) {
public User getUserByEmail(String email, UserSignupType signupType) {
try {
TypedQuery<User> query = em.createQuery("SELECT u FROM User u WHERE u.email = :email", User.class);
TypedQuery<User> query = em.createQuery("SELECT u FROM User u WHERE u.email = :email AND u.signupType = :userSignupType AND u.status = 'ACTIVE'", User.class);
query.setParameter("email", email);
query.setParameter("userSignupType", signupType.getSignupType());
return query.getSingleResult();
} catch (NoResultException e) {
return null;
Expand Down
Loading

0 comments on commit 868cb9b

Please sign in to comment.