diff --git a/src/main/java/com/example/namo2/domain/category/application/CategoryFacade.java b/src/main/java/com/example/namo2/domain/category/application/CategoryFacade.java index 56fbc4b84..0786e9105 100644 --- a/src/main/java/com/example/namo2/domain/category/application/CategoryFacade.java +++ b/src/main/java/com/example/namo2/domain/category/application/CategoryFacade.java @@ -44,15 +44,16 @@ public List getCategories(Long userId) { } @Transactional(readOnly = false) - public CategoryResponse.CategoryIdDto modifyCategory(Long categoryId, CategoryRequest.PostCategoryDto dto) { + public CategoryResponse.CategoryIdDto modifyCategory(Long categoryId, CategoryRequest.PostCategoryDto dto, + Long userId) { Palette palette = paletteService.getPalette(dto.getPaletteId()); - Category modifiedCategory = categoryService.modifyCategory(categoryId, dto, palette); + Category modifiedCategory = categoryService.modifyCategory(categoryId, dto, palette, userId); return CategoryResponseConverter.toCategoryIdDto(modifiedCategory); } @Transactional(readOnly = false) - public void deleteCategory(Long categoryId) { - categoryService.delete(categoryId); + public void deleteCategory(Long categoryId, Long userId) { + categoryService.delete(categoryId, userId); } } diff --git a/src/main/java/com/example/namo2/domain/category/application/converter/CategoryConverter.java b/src/main/java/com/example/namo2/domain/category/application/converter/CategoryConverter.java index 2ca660bc2..2f0eb534e 100644 --- a/src/main/java/com/example/namo2/domain/category/application/converter/CategoryConverter.java +++ b/src/main/java/com/example/namo2/domain/category/application/converter/CategoryConverter.java @@ -1,6 +1,7 @@ package com.example.namo2.domain.category.application.converter; import com.example.namo2.domain.category.domain.Category; +import com.example.namo2.domain.category.domain.CategoryKind; import com.example.namo2.domain.category.domain.Palette; import com.example.namo2.domain.category.ui.dto.CategoryRequest; @@ -22,6 +23,7 @@ public static Category toCategory( .user(user) .palette(palette) .share(dto.isShare()) + .kind(CategoryKind.CUSTOM) .build(); } @@ -29,13 +31,15 @@ public static Category toCategory( String name, Palette palette, Boolean isShare, - User user + User user, + CategoryKind kind ) { return Category.builder() .name(name) .palette(palette) .share(isShare) .user(user) + .kind(kind) .build(); } } diff --git a/src/main/java/com/example/namo2/domain/category/application/impl/CategoryService.java b/src/main/java/com/example/namo2/domain/category/application/impl/CategoryService.java index 1201265ba..e97692421 100644 --- a/src/main/java/com/example/namo2/domain/category/application/impl/CategoryService.java +++ b/src/main/java/com/example/namo2/domain/category/application/impl/CategoryService.java @@ -8,6 +8,7 @@ import com.example.namo2.domain.category.dao.repository.CategoryRepository; import com.example.namo2.domain.category.domain.Category; +import com.example.namo2.domain.category.domain.CategoryKind; import com.example.namo2.domain.category.domain.CategoryStatus; import com.example.namo2.domain.category.domain.Palette; import com.example.namo2.domain.category.ui.dto.CategoryRequest; @@ -15,6 +16,7 @@ import com.example.namo2.domain.user.domain.User; import com.example.namo2.global.common.exception.BaseException; +import com.example.namo2.global.common.response.BaseResponseStatus; import lombok.RequiredArgsConstructor; @@ -31,8 +33,9 @@ public List getCategories(Long userId) { return categoryRepository.findCategoriesByUserIdAndStatusEquals(userId, CategoryStatus.ACTIVE); } - public void delete(Long categoryId) { + public void delete(Long categoryId, Long userId) { Category category = getCategory(categoryId); + validateUsersCategory(userId, category); validateBaseCategory(category); category.delete(); } @@ -46,20 +49,26 @@ public Category getCategory(Long categoryId) { .orElseThrow(() -> new BaseException(NOT_FOUND_CATEGORY_FAILURE)); } - public Category modifyCategory(Long categoryId, CategoryRequest.PostCategoryDto dto, Palette palette) { + public Category modifyCategory(Long categoryId, CategoryRequest.PostCategoryDto dto, Palette palette, Long userId) { Category category = getCategory(categoryId); - validateBaseCategory(category); + validateUsersCategory(userId, category); category.update(dto.getName(), dto.isShare(), palette); return category; } - private static void validateBaseCategory(Category category) { - if (category.getName().equals("일정") || category.getName().equals("모임")) { + private void validateUsersCategory(Long userId, Category category) { + if (category.isNotCreatedByUser(userId)) { + throw new BaseException(BaseResponseStatus.NOT_USERS_CATEGORY); + } + } + + private void validateBaseCategory(Category category) { + if (category.isBaseCategory()) { throw new BaseException(NOT_DELETE_BASE_CATEGORY_FAILURE); } } public List getMoimUsersCategories(List users) { - return categoryRepository.findMoimCategoriesByUsers(users); + return categoryRepository.findMoimCategoriesByUsers(users, CategoryKind.MOIM); } } diff --git a/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepository.java b/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepository.java index 286bf2c5a..27a349da5 100644 --- a/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepository.java +++ b/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepository.java @@ -3,22 +3,10 @@ import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import com.example.namo2.domain.category.domain.Category; import com.example.namo2.domain.category.domain.CategoryStatus; -import com.example.namo2.domain.user.domain.User; - -public interface CategoryRepository extends JpaRepository { - public List findCategoriesByUserIdAndStatusEquals(Long userId, CategoryStatus status); - - @Query(value = "select c" - + " from Category c" - + " join fetch c.user" - + " where c.user in :users and c.name = '모임'") - List findMoimCategoriesByUsers(@Param("users") List users); - - void deleteAllByUser(User user); +public interface CategoryRepository extends JpaRepository, CategoryRepositoryCustom { + List findCategoriesByUserIdAndStatusEquals(Long userId, CategoryStatus status); } diff --git a/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepositoryCustom.java b/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepositoryCustom.java new file mode 100644 index 000000000..5499c5e48 --- /dev/null +++ b/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepositoryCustom.java @@ -0,0 +1,14 @@ +package com.example.namo2.domain.category.dao.repository; + +import java.util.List; + +import org.springframework.data.repository.query.Param; + +import com.example.namo2.domain.category.domain.Category; +import com.example.namo2.domain.category.domain.CategoryKind; + +import com.example.namo2.domain.user.domain.User; + +public interface CategoryRepositoryCustom { + List findMoimCategoriesByUsers(@Param("users") List users, @Param("kind") CategoryKind kind); +} diff --git a/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepositoryImpl.java b/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepositoryImpl.java new file mode 100644 index 000000000..3832d831c --- /dev/null +++ b/src/main/java/com/example/namo2/domain/category/dao/repository/CategoryRepositoryImpl.java @@ -0,0 +1,32 @@ +package com.example.namo2.domain.category.dao.repository; + +import static com.example.namo2.domain.category.domain.QCategory.*; + +import java.util.List; + +import jakarta.persistence.EntityManager; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +import com.example.namo2.domain.category.domain.Category; +import com.example.namo2.domain.category.domain.CategoryKind; + +import com.example.namo2.domain.user.domain.User; + +public class CategoryRepositoryImpl implements CategoryRepositoryCustom { + private final JPAQueryFactory queryFactory; + + public CategoryRepositoryImpl(EntityManager em) { + queryFactory = new JPAQueryFactory(em); + } + + @Override + public List findMoimCategoriesByUsers(List users, CategoryKind kind) { + return queryFactory + .selectFrom(category) + .join(category.user).fetchJoin() + .where(category.user.in(users), + category.kind.eq(kind)) + .fetch(); + } +} diff --git a/src/main/java/com/example/namo2/domain/category/domain/Category.java b/src/main/java/com/example/namo2/domain/category/domain/Category.java index bf8ea635c..1d9dde768 100644 --- a/src/main/java/com/example/namo2/domain/category/domain/Category.java +++ b/src/main/java/com/example/namo2/domain/category/domain/Category.java @@ -46,13 +46,17 @@ public class Category extends BaseTimeEntity { @Enumerated(EnumType.STRING) private CategoryStatus status; + @Enumerated(EnumType.STRING) + private CategoryKind kind; + @Builder - public Category(Palette palette, User user, String name, Boolean share) { + public Category(Palette palette, User user, String name, Boolean share, CategoryKind kind) { this.palette = palette; this.user = user; this.name = name; this.share = share; this.status = CategoryStatus.ACTIVE; + this.kind = kind; } public void update(String name, Boolean share, Palette palette) { @@ -64,4 +68,15 @@ public void update(String name, Boolean share, Palette palette) { public void delete() { this.status = CategoryStatus.DELETE; } + + public boolean isNotCreatedByUser(Long userId) { + return this.user.getId() != userId; + } + + public boolean isBaseCategory() { + if (kind == CategoryKind.SCHEDULE || kind == CategoryKind.MOIM) { + return true; + } + return false; + } } diff --git a/src/main/java/com/example/namo2/domain/category/domain/CategoryKind.java b/src/main/java/com/example/namo2/domain/category/domain/CategoryKind.java new file mode 100644 index 000000000..dcbce20d2 --- /dev/null +++ b/src/main/java/com/example/namo2/domain/category/domain/CategoryKind.java @@ -0,0 +1,20 @@ +package com.example.namo2.domain.category.domain; + +public enum CategoryKind { + /* + SCHEDULE: 기본 + MOIM: MOIM 기본 + CUSTOM: 유저가 생성한 카테고리 + */ + SCHEDULE("일정"), MOIM("모임"), CUSTOM("커스텀"); + + private String categoryName; + + CategoryKind(String categoryName) { + this.categoryName = categoryName; + } + + public String getCategoryName() { + return categoryName; + } +} diff --git a/src/main/java/com/example/namo2/domain/category/ui/CategoryController.java b/src/main/java/com/example/namo2/domain/category/ui/CategoryController.java index e33f40d9d..8f3985c19 100644 --- a/src/main/java/com/example/namo2/domain/category/ui/CategoryController.java +++ b/src/main/java/com/example/namo2/domain/category/ui/CategoryController.java @@ -53,15 +53,20 @@ public BaseResponse> findAllCategory(HttpServ @Operation(summary = "카테고리 수정", description = "카테고리 수정 API") @PatchMapping("/{categoryId}") public BaseResponse updateCategory(@PathVariable("categoryId") Long categoryId, - @Valid @RequestBody CategoryRequest.PostCategoryDto postcategoryDto) { - CategoryResponse.CategoryIdDto categoryIdDto = categoryFacade.modifyCategory(categoryId, postcategoryDto); + @Valid @RequestBody CategoryRequest.PostCategoryDto postcategoryDto, + HttpServletRequest request) { + Long userId = (Long)request.getAttribute("userId"); + CategoryResponse.CategoryIdDto categoryIdDto = categoryFacade.modifyCategory(categoryId, postcategoryDto, + userId); return new BaseResponse<>(categoryIdDto); } @Operation(summary = "카테고리 삭제", description = "카테고리 삭제 API") @DeleteMapping("/{categoryId}") - public BaseResponse deleteCategory(@PathVariable("categoryId") Long categoryId) { - categoryFacade.deleteCategory(categoryId); + public BaseResponse deleteCategory(@PathVariable("categoryId") Long categoryId, + HttpServletRequest request) { + Long userId = (Long)request.getAttribute("userId"); + categoryFacade.deleteCategory(categoryId, userId); return new BaseResponse<>("삭제에 성공하셨습니다."); } diff --git a/src/main/java/com/example/namo2/domain/category/ui/dto/CategoryRequest.java b/src/main/java/com/example/namo2/domain/category/ui/dto/CategoryRequest.java index a26632f96..bb2346701 100644 --- a/src/main/java/com/example/namo2/domain/category/ui/dto/CategoryRequest.java +++ b/src/main/java/com/example/namo2/domain/category/ui/dto/CategoryRequest.java @@ -1,9 +1,8 @@ package com.example.namo2.domain.category.ui.dto; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import com.example.namo2.domain.category.validation.annotation.CategoryName; - import lombok.AllArgsConstructor; import lombok.Getter; @@ -16,7 +15,7 @@ private CategoryRequest() { @AllArgsConstructor @Getter public static class PostCategoryDto { - @CategoryName + @NotBlank private String name; @NotNull private Long paletteId; diff --git a/src/main/java/com/example/namo2/domain/category/validation/annotation/CategoryName.java b/src/main/java/com/example/namo2/domain/category/validation/annotation/CategoryName.java deleted file mode 100644 index b41d28ab3..000000000 --- a/src/main/java/com/example/namo2/domain/category/validation/annotation/CategoryName.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.example.namo2.domain.category.validation.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; - -import com.example.namo2.domain.category.validation.validator.CategoryValidator; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@Constraint(validatedBy = CategoryValidator.class) -public @interface CategoryName { - String message() default "카테고리 이름에는 일정, 모임이 들어갈 수 없습니다."; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/src/main/java/com/example/namo2/domain/category/validation/validator/CategoryValidator.java b/src/main/java/com/example/namo2/domain/category/validation/validator/CategoryValidator.java deleted file mode 100644 index 157ba23af..000000000 --- a/src/main/java/com/example/namo2/domain/category/validation/validator/CategoryValidator.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.namo2.domain.category.validation.validator; - -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; - -import com.example.namo2.domain.category.validation.annotation.CategoryName; - -public class CategoryValidator implements ConstraintValidator { - - public static final String BASE_SCHEDULE_CATEGORY = "일정"; - public static final String BASE_MOIM_CATEGORY = "모임"; - - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - if (value == null || value.isBlank()) { - return false; - } - if (value.equals(BASE_SCHEDULE_CATEGORY) || value.equals(BASE_MOIM_CATEGORY)) { - return false; - } - return true; - } -} diff --git a/src/main/java/com/example/namo2/domain/user/application/UserFacade.java b/src/main/java/com/example/namo2/domain/user/application/UserFacade.java index 074b27b37..3da42bf10 100644 --- a/src/main/java/com/example/namo2/domain/user/application/UserFacade.java +++ b/src/main/java/com/example/namo2/domain/user/application/UserFacade.java @@ -49,6 +49,7 @@ import com.example.namo2.domain.category.application.impl.CategoryService; import com.example.namo2.domain.category.application.impl.PaletteService; import com.example.namo2.domain.category.domain.Category; +import com.example.namo2.domain.category.domain.CategoryKind; import com.example.namo2.domain.memo.application.impl.MoimMemoLocationService; @@ -285,16 +286,18 @@ private User saveOrNot(User user) { private void makeBaseCategory(User save) { Category baseCategory = CategoryConverter.toCategory( - "일정", + CategoryKind.SCHEDULE.getCategoryName(), paletteService.getReferenceById(1L), Boolean.TRUE, - save + save, + CategoryKind.SCHEDULE ); Category groupCategory = CategoryConverter.toCategory( - "모임", + CategoryKind.MOIM.getCategoryName(), paletteService.getReferenceById(4L), Boolean.TRUE, - save + save, + CategoryKind.MOIM ); categoryService.create(baseCategory); diff --git a/src/main/java/com/example/namo2/global/common/response/BaseResponseStatus.java b/src/main/java/com/example/namo2/global/common/response/BaseResponseStatus.java index 54c88d605..256f3970a 100644 --- a/src/main/java/com/example/namo2/global/common/response/BaseResponseStatus.java +++ b/src/main/java/com/example/namo2/global/common/response/BaseResponseStatus.java @@ -39,7 +39,7 @@ public enum BaseResponseStatus { /** * NOT FOUND 오류 - * 404 번오류 + * 404 */ NOT_FOUND_USER_FAILURE(404, "유저를 찾을 수 없습니다."), NOT_FOUND_SCHEDULE_FAILURE(404, "스케줄을 찾을 수 없습니다."), @@ -66,6 +66,11 @@ public enum BaseResponseStatus { DUPLICATE_PARTICIPATE_FAILURE(404, "이미 가입한 모임입니다."), DUPLICATE_MOIM_MEMO_FAILURE(404, "이미 모임 메모가 생성되어 있습니다."), + /** + * 404 오용 오류 + */ + NOT_USERS_CATEGORY(404, "잘못된 접근 요청입니다.."), + /** * 404: 인프라 에러 */ diff --git a/src/main/java/com/example/namo2/global/utils/SocialUtils.java b/src/main/java/com/example/namo2/global/utils/SocialUtils.java index 4f183ed53..c83c2a8a4 100644 --- a/src/main/java/com/example/namo2/global/utils/SocialUtils.java +++ b/src/main/java/com/example/namo2/global/utils/SocialUtils.java @@ -68,7 +68,13 @@ public Map findResponseFromNaver(String result) throws BaseExcep if (!jsonMap.get("resultcode").equals("00")) { throw new BaseException(SOCIAL_LOGIN_FAILURE); } - return (Map)jsonMap.get("response"); + /** + * 네이버 로그인 시에는 nickname이 null 값으로 받아집니다. + * toUser를 일원화시키려면 아래 같은 식으로 name 값을 nickname 값으로 바꿔주셔야해요. + */ + Map response = (Map)jsonMap.get("response"); + response.put("nickname", response.get("name")); + return response; } public Map findResponseFromKakako(String result) throws BaseException {