Skip to content

Commit

Permalink
Merge pull request #22 from KUSITMS-CORECORD/chore/#21
Browse files Browse the repository at this point in the history
[Chore/#21] Folder-User Mapping
  • Loading branch information
daeun084 authored Oct 28, 2024
2 parents a2bda8f + f0ebbd8 commit 4ded01c
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
public enum FolderSuccessStatus implements BaseSuccessStatus {

FOLDER_CREATE_SUCCESS(HttpStatus.CREATED, "S601", "폴더 생성이 성공적으로 완료되었습니다."),
FOLDER_DELETE_SUCCESS(HttpStatus.OK, "S601", "폴더 삭제 성공적으로 완료되었습니다."),
FOLDER_GET_SUCCESS(HttpStatus.OK, "S601", "폴더 리스트 조회가 성공적으로 완료되었습니다."),
FOLDER_UPDATE_SUCCESS(HttpStatus.OK, "S601", "폴더 수정이 성공적으로 완료되었습니다.");
FOLDER_DELETE_SUCCESS(HttpStatus.OK, "S605", "폴더 삭제가 성공적으로 완료되었습니다."),
FOLDER_GET_SUCCESS(HttpStatus.OK, "S603", "폴더 리스트 조회가 성공적으로 완료되었습니다."),
FOLDER_UPDATE_SUCCESS(HttpStatus.OK, "S604", "폴더명 수정이 성공적으로 완료되었습니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package corecord.dev.domain.folder.controller;

import corecord.dev.common.response.ApiResponse;
import corecord.dev.common.web.UserId;
import corecord.dev.domain.folder.constant.FolderSuccessStatus;
import corecord.dev.domain.folder.dto.request.FolderRequest;
import corecord.dev.domain.folder.dto.response.FolderResponse;
Expand All @@ -17,36 +18,36 @@ public class FolderController {

@PostMapping("")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> createFolder(
@UserId Long userId,
@RequestBody FolderRequest.FolderDto folderDto
) {
FolderResponse.FolderDtoList folderResponse = folderService.createFolder(folderDto);

FolderResponse.FolderDtoList folderResponse = folderService.createFolder(userId, folderDto);
return ApiResponse.success(FolderSuccessStatus.FOLDER_CREATE_SUCCESS, folderResponse);
}

@DeleteMapping("/{folderId}")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> deleteFolder(
@UserId Long userId,
@PathVariable(name = "folderId") Long folderId
) {
FolderResponse.FolderDtoList folderResponse = folderService.deleteFolder(folderId);

FolderResponse.FolderDtoList folderResponse = folderService.deleteFolder(userId, folderId);
return ApiResponse.success(FolderSuccessStatus.FOLDER_DELETE_SUCCESS, folderResponse);
}

@GetMapping("")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> getFolders(
@UserId Long userId
) {
FolderResponse.FolderDtoList folderResponse = folderService.getFolderList();

FolderResponse.FolderDtoList folderResponse = folderService.getFolderList(userId);
return ApiResponse.success(FolderSuccessStatus.FOLDER_GET_SUCCESS, folderResponse);
}

@PatchMapping("")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> updateFolder(
@UserId Long userId,
@RequestBody FolderRequest.FolderUpdateDto folderDto
) {
FolderResponse.FolderDtoList folderResponse = folderService.updateFolder(folderDto);

FolderResponse.FolderDtoList folderResponse = folderService.updateFolder(userId, folderDto);
return ApiResponse.success(FolderSuccessStatus.FOLDER_UPDATE_SUCCESS, folderResponse);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@

import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.entity.Folder;
import corecord.dev.domain.user.entity.User;

import java.util.List;

public class FolderConverter {

public static Folder toFolderEntity(String title) {
public static Folder toFolderEntity(String title, User user) {
return Folder.builder()
.title(title)
.user(user)
.build();
}

public static FolderResponse.FolderDto toFolderDto(Folder folder) {
return FolderResponse.FolderDto.builder()
.folderId(folder.getFolderId())
.title(folder.getTitle())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package corecord.dev.domain.folder.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Data;

public class FolderRequest {

@Data
public static class FolderDto {
@NotBlank(message = "폴더 명을 입력해주세요.")
private String title;
}

@Data
public static class FolderUpdateDto {
@NotBlank(message = "수정할 폴더 id를 입력해주세요.")
private Long folderId;
@NotBlank(message = "수정할 폴더 명을 입력해주세요.")
private String title;
}
}
5 changes: 5 additions & 0 deletions src/main/java/corecord/dev/domain/folder/entity/Folder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import corecord.dev.common.base.BaseEntity;
import corecord.dev.domain.record.entity.Record;
import corecord.dev.domain.user.entity.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand All @@ -26,6 +27,10 @@ public class Folder extends BaseEntity {
@OneToOne(mappedBy = "folder")
private Record record;

@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;

public void updateTitle(String title) {
this.title = title;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
public enum FolderErrorStatus implements BaseErrorStatus {
DUPLICATED_FOLDER_TITLE(HttpStatus.BAD_REQUEST, "E0400_DUPLICATED_TITLE", "이미 존재하는 폴더 명입니다."),
OVERFLOW_FOLDER_TITLE(HttpStatus.BAD_REQUEST, "E0400_OVERFLOW_TITLE", "폴더 명은 15자 이내여야 합니다."),
USER_FOLDER_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "E401_FOLDER_UNAUTHORIZED", "유저가 폴더에 대한 권한이 없습니다."),
FOLDER_NOT_FOUND(HttpStatus.NOT_FOUND, "E0404_FOLDER", "존재하지 않는 폴더입니다.");

private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.entity.Folder;
import corecord.dev.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
Expand All @@ -13,8 +15,9 @@ public interface FolderRepository extends JpaRepository<Folder, Long> {

@Query("SELECT new corecord.dev.domain.folder.dto.response.FolderResponse$FolderDto(f.folderId, f.title) " +
"FROM Folder f " +
"ORDER BY f.createdAt")
List<FolderResponse.FolderDto> findFolderDtoList();
"WHERE f.user = :user " +
"ORDER BY f.createdAt desc ")
List<FolderResponse.FolderDto> findFolderDtoList(@Param(value = "user") User user);

boolean existsByTitle(String title);
}
82 changes: 57 additions & 25 deletions src/main/java/corecord/dev/domain/folder/service/FolderService.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package corecord.dev.domain.folder.service;

import corecord.dev.common.exception.GeneralException;
import corecord.dev.common.status.ErrorStatus;
import corecord.dev.domain.folder.converter.FolderConverter;
import corecord.dev.domain.folder.dto.request.FolderRequest;
import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.entity.Folder;
import corecord.dev.domain.folder.exception.enums.FolderErrorStatus;
import corecord.dev.domain.folder.exception.model.FolderException;
import corecord.dev.domain.folder.repository.FolderRepository;
import corecord.dev.domain.user.entity.User;
import corecord.dev.domain.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
Expand All @@ -19,78 +23,106 @@
@RequiredArgsConstructor
public class FolderService {
private final FolderRepository folderRepository;
private final UserRepository userRepository;

/*
* 폴더명(title)을 request로 받아, 새로운 폴더를 생성
* @param folderDto
* 폴더명(title)을 request로 받아, 새로운 폴더를 생성 후 생성 순 풀더 리스트 반환
* @param userId, folderDto
* @return
*/
@Transactional
public FolderResponse.FolderDtoList createFolder(FolderRequest.FolderDto folderDto) {
validateDuplicatedFolderTitle(folderDto.getTitle());
public FolderResponse.FolderDtoList createFolder(Long userId, FolderRequest.FolderDto folderDto) {
User user = findUserById(userId);
String title = folderDto.getTitle();

Folder folder = FolderConverter.toFolderEntity(folderDto.getTitle());
// 폴더명 유효성 검증
validDuplicatedFolderTitleAndLength(title);

// folder 객체 생성 및 User 연관관계 설정
Folder folder = FolderConverter.toFolderEntity(title, user);
folderRepository.save(folder);

return getFolderList();
return getFolderList(userId);
}

/*
* folderId를 통해 folder을 삭제
* @param folderId
* folderId를 받아 folder를 삭제한 후 생성 순 폴더 리스트 반환
* @param userId, folderId
* @return
*/
@Transactional
public FolderResponse.FolderDtoList deleteFolder(Long folderId) {
public FolderResponse.FolderDtoList deleteFolder(Long userId, Long folderId) {
User user = findUserById(userId);
Folder folder = findFolderById(folderId);

// User-Folder 권한 유효성 검증
validIsUserAuthorizedForFolder(user, folder);

folderRepository.delete(folder);

return getFolderList();
return getFolderList(userId);
}

/*
* folderId를 받아, 해당 folder의 title을 수정
* @param folderDto
* @param userId, folderDto
* @return
*/
@Transactional
public FolderResponse.FolderDtoList updateFolder(FolderRequest.FolderUpdateDto folderDto) {
public FolderResponse.FolderDtoList updateFolder(Long userId, FolderRequest.FolderUpdateDto folderDto) {
User user = findUserById(userId);
Folder folder = findFolderById(folderDto.getFolderId());
String title = folderDto.getTitle();

// 폴더명 유효성 검증
validDuplicatedFolderTitleAndLength(title);

validateDuplicatedFolderTitle(folderDto.getTitle());
validateTitleLength(folderDto.getTitle());
// User-Folder 권한 유효성 검증
validIsUserAuthorizedForFolder(user, folder);

folder.updateTitle(folderDto.getTitle());
folder.updateTitle(title);

return getFolderList();
return getFolderList(userId);
}

/*
* 생성일 오름차순으로 폴더 리스트를 조회
* @param userId
* @return
*/
@Transactional(readOnly = true)
public FolderResponse.FolderDtoList getFolderList() {
List<FolderResponse.FolderDto> folderList = folderRepository.findFolderDtoList();
public FolderResponse.FolderDtoList getFolderList(Long userId) {
User user = findUserById(userId);

List<FolderResponse.FolderDto> folderList = folderRepository.findFolderDtoList(user);
return FolderConverter.toFolderDtoList(folderList);
}

// 폴더명 중복 검사
private void validateDuplicatedFolderTitle(String title) {
private void validDuplicatedFolderTitleAndLength(String title) {
// 폴더명 글자 수 검사
if (title.length() > 15) {
throw new FolderException(FolderErrorStatus.OVERFLOW_FOLDER_TITLE);
}

// 폴더명 중복 검사
if (folderRepository.existsByTitle(title)) {
throw new FolderException(FolderErrorStatus.DUPLICATED_FOLDER_TITLE);
}
}

// title 글자 수 검사
private void validateTitleLength(String title) {
if (title.length() > 15) {
throw new FolderException(FolderErrorStatus.OVERFLOW_FOLDER_TITLE);
}
// user-folder 권한 검사
private void validIsUserAuthorizedForFolder(User user, Folder folder) {
if (!folder.getUser().equals(user))
throw new FolderException(FolderErrorStatus.USER_FOLDER_UNAUTHORIZED);
}

private Folder findFolderById(Long folderId) {
return folderRepository.findById(folderId)
.orElseThrow(() -> new FolderException(FolderErrorStatus.FOLDER_NOT_FOUND));
}

private User findUserById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new GeneralException(ErrorStatus.UNAUTHORIZED));
}
}
5 changes: 4 additions & 1 deletion src/main/java/corecord/dev/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import corecord.dev.common.base.BaseEntity;
import corecord.dev.domain.analysis.entity.Ability;
import corecord.dev.domain.chat.entity.ChatRoom;
import corecord.dev.domain.folder.entity.Folder;
import corecord.dev.domain.record.entity.Record;
import jakarta.persistence.*;
import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Entity
Expand Down Expand Up @@ -48,4 +48,7 @@ public class User extends BaseEntity {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Ability> abilities;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Folder> folders;

}

0 comments on commit 4ded01c

Please sign in to comment.