From 38f9481b9a3221cdf51ffcc49e85a27fb0d4e900 Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Mon, 9 Dec 2024 14:07:59 +0900 Subject: [PATCH 01/46] =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refrigerator/build.gradle | 3 +-- .../refrigerator/aggregate/ingredient/IngredientCategory.java | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java diff --git a/refrigerator/build.gradle b/refrigerator/build.gradle index 4fec5bf..d1f5710 100644 --- a/refrigerator/build.gradle +++ b/refrigerator/build.gradle @@ -31,11 +31,10 @@ dependencies { developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' + runtimeOnly 'com.mysql:mysql-connector-j' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.modelmapper:modelmapper:3.1.0' - } tasks.named('test') { diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java new file mode 100644 index 0000000..7ab620e --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java @@ -0,0 +1,4 @@ +package moja.refrigerator.aggregate.ingredient; + +public class IngredientCategory { +} From 2d8262dd6f8f2de5cf30f7c7a07db73d88fd36ef Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Mon, 9 Dec 2024 14:40:15 +0900 Subject: [PATCH 02/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=EA=B4=80?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 재료관리 entity 추가 2. 재료관리 service, controller, repository 추가 3. user dummy entity 추가 Resolves: #1 --- .../ingredient/IngredientBookmark.java | 24 +++++++++++++ .../ingredient/IngredientCategory.java | 14 ++++++++ .../ingredient/IngredientManagement.java | 35 +++++++++++++++++++ .../ingredient/IngredientStorage.java | 17 +++++++++ .../refrigerator/aggregate/user/User.java | 14 ++++++++ .../ingredient/IngredientController.java | 17 +++++++++ .../IngredientManagementRepository.java | 7 ++++ .../service/ingredient/IngredientService.java | 4 +++ .../ingredient/IngredientServiceImpl.java | 20 +++++++++++ 9 files changed, 152 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java new file mode 100644 index 0000000..5f7a32b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java @@ -0,0 +1,24 @@ +package moja.refrigerator.aggregate.ingredient; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Table(name = "tbl_ingredient_bookmark") +@Entity +@Data +public class IngredientBookmark { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ingredient_bookmark_pk") + private long ingredientBookmarkPk; + + @ManyToOne + @JoinColumn(name = "user") + private User user; + + @ManyToOne + @JoinColumn(name = "ingredient_management") + private IngredientManagement ingredientManagement; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java index 7ab620e..94f0113 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java @@ -1,4 +1,18 @@ package moja.refrigerator.aggregate.ingredient; +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "tbl_ingredient_category") +@Data public class IngredientCategory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ingredient_category_pk") + private int IngredientCategoryPk; + + @Column(name = "ingredient_category") + private String IngredientCategory; } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java new file mode 100644 index 0000000..5a9e5bb --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java @@ -0,0 +1,35 @@ +package moja.refrigerator.aggregate.ingredient; + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name = "tbl_ingredient_management") +public class IngredientManagement { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ingredient_management_pk") + private long ingredientManagementPk; + + @Column(name = "ingredient_name") + private String ingredientName; + + @Column(name = "expiration_date") + private String expirationDate; + + @Column(name = "registration_date") + private String registrationDate; + + @Column(name = "season_date") + private int seasonDate; + + @JoinColumn(name = "ingredient_category") + @ManyToOne + private IngredientCategory ingredientCategory; + + @JoinColumn(name = "ingredient_storage") + @ManyToOne + private IngredientStorage ingredientStorage; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java new file mode 100644 index 0000000..0413b68 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java @@ -0,0 +1,17 @@ +package moja.refrigerator.aggregate.ingredient; + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name="tbl_ingredient_storage") +public class IngredientStorage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ingredient_storage_pk") + private int IngredientStoragePk; + + @Column(name = "ingredient_storage") + private String IngredientStorage; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java new file mode 100644 index 0000000..a352fc0 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java @@ -0,0 +1,14 @@ +package moja.refrigerator.aggregate.user; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "tbl_user") +@Data +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_pk") + private long userPk; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java new file mode 100644 index 0000000..94315c0 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -0,0 +1,17 @@ +package moja.refrigerator.controller.ingredient; + +import moja.refrigerator.service.ingredient.IngredientService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/ingredient") +public class IngredientController { + private IngredientService ingredientService; + + @Autowired + public IngredientController(IngredientService ingredientService) { + this.ingredientService = ingredientService; + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java new file mode 100644 index 0000000..e71665c --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java @@ -0,0 +1,7 @@ +package moja.refrigerator.repository.ingredient; + +import moja.refrigerator.aggregate.ingredient.IngredientManagement; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface IngredientManagementRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java new file mode 100644 index 0000000..92b1ac0 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -0,0 +1,4 @@ +package moja.refrigerator.service.ingredient; + +public interface IngredientService { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java new file mode 100644 index 0000000..8dd1aeb --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -0,0 +1,20 @@ +package moja.refrigerator.service.ingredient; + +import moja.refrigerator.repository.ingredient.IngredientManagementRepository; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class IngredientServiceImpl implements IngredientService{ + + private IngredientManagementRepository ingredientManagementRepository; + private ModelMapper mapper; + + @Autowired + public IngredientServiceImpl(IngredientManagementRepository ingredientManagementRepository, + ModelMapper mapper) { + this.ingredientManagementRepository = ingredientManagementRepository; + this.mapper = mapper; + } +} From 7ab95e999831764cdca12cdab7b0f2029a6025fb Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Mon, 9 Dec 2024 14:57:59 +0900 Subject: [PATCH 03/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=EA=B4=80?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Repository 수정 Fixes: #1 --- .../repository/ingredient/IngredientManagementRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java index e71665c..c9619a4 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java @@ -3,5 +3,5 @@ import moja.refrigerator.aggregate.ingredient.IngredientManagement; import org.springframework.data.jpa.repository.JpaRepository; -public interface IngredientManagementRepository extends JpaRepository { +public interface IngredientManagementRepository extends JpaRepository { } From 335df918fcc45242140166e6763950cd7054b3e7 Mon Sep 17 00:00:00 2001 From: LeeGukgeon Date: Mon, 9 Dec 2024 18:04:44 +0900 Subject: [PATCH 04/46] recipe aggregate, controller, repository, service basic --- .../aggregate/recipe/Comment.java | 30 ++++++++++++ .../refrigerator/aggregate/recipe/Recipe.java | 46 +++++++++++++++++++ .../aggregate/recipe/RecipeCategory.java | 17 +++++++ .../aggregate/recipe/RecipeIngredient.java | 26 +++++++++++ .../aggregate/recipe/RecipeLike.java | 24 ++++++++++ .../aggregate/recipe/RecipeSource.java | 30 ++++++++++++ .../aggregate/recipe/RecipeSourceType.java | 18 ++++++++ .../recipe/ReplacableIngredient.java | 23 ++++++++++ .../controller/recipe/RecipeController.java | 17 +++++++ .../repository/recipe/RecipeRepository.java | 8 ++++ .../service/recipe/RecipeService.java | 4 ++ .../service/recipe/RecipeServiceImpl.java | 20 ++++++++ 12 files changed, 263 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLike.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java new file mode 100644 index 0000000..21d300a --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java @@ -0,0 +1,30 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Data +@Entity +@Table(name = "tbl_comment") +public class Comment { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "comment_pk") + private long CommentPk ; + + @Column(name = "comment_create_time") + private String CommentCreateTime ; + @Column(name = "comment_update_time") + private String CommentUpdateTime ; + @Column(name = "comment_contents") + private String CommentContents ; + + @JoinColumn(name = "user") + @ManyToOne + private User user ; + + @JoinColumn(name = "recipe") + @ManyToOne + private Recipe recipe ; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java new file mode 100644 index 0000000..aa32223 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -0,0 +1,46 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Data +@Entity +@Table(name = "tbl_recipe") +public class Recipe { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "recipe_pk") + private long recipePk; + + @Column(name = "recipe_name") + private String recipeName; + + @Column(name = "recipe_cooking_time") + private int recipeCookingTime; + + @Column(name = "recipe_create_time") + private String recipeCreateTime; + + @Column(name = "recipe_update_time") + private String recipeUpdateTime; + + @Column(name = "recipe_difficulty") + private int recipeDifficulty; + + @Column(name = "recipe_views") + private long recipeViews; + + @JoinColumn(name = "user") + @ManyToOne + private User user; + + @JoinColumn(name = "cooking_source") + @ManyToOne + private RecipeSource recipeSource; + + @JoinColumn(name = "recipe_category") + @ManyToOne + private RecipeCategory recipeCategory; +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java new file mode 100644 index 0000000..8fb98cd --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java @@ -0,0 +1,17 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name="tbl_recipe_category") +public class RecipeCategory { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "recipe_category_pk") + private int RecipeCategoryPK; + + @Column(name = "recipe_category") + private String recipeCategory; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java new file mode 100644 index 0000000..e530f63 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java @@ -0,0 +1,26 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.ingredient.IngredientManagement; + +@Data +@Entity +@Table(name = "tbl_recipe_ingredient") +public class RecipeIngredient { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "recipe_ingredient_pk") + private long recipeIngredientPk ; + + @Column(name = "ingredient_is_necessary") + private boolean ingredientIsNecessary ; + + @JoinColumn(name = "ingredient_management") + @ManyToOne + private IngredientManagement ingredientManagement; + + @JoinColumn(name = "recipe") + @ManyToOne + private Recipe recipe; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLike.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLike.java new file mode 100644 index 0000000..402462a --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLike.java @@ -0,0 +1,24 @@ +package moja.refrigerator.aggregate.recipe; + + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Data +@Entity +@Table(name="tbl_recipe_like") +public class RecipeLike { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "like_pk") + private long likePk; + + @JoinColumn(name = "user") + @ManyToOne + private User user; + + @JoinColumn(name = "recipe") + @ManyToOne + private Recipe recipe; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java new file mode 100644 index 0000000..85c63ef --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -0,0 +1,30 @@ +package moja.refrigerator.aggregate.recipe; + + +import jakarta.persistence.*; +import lombok.Data; + +@Data +@Entity +@Table(name="tbl_recipe_source") +public class RecipeSource { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "cooking_source_pk") + private long cookingSourcePk; + + @Column(name = "cooking_source_save") + private String cookingSourceSave; + + @Column(name = "cooking_source_create_time") + private String CookingSourceCreateTime; + + @Column(name = "cooking_source_file_name") + private String CookingSourceFileName; + + @JoinColumn(name = "cooking_source_type") + @OneToOne + private RecipeSourceType cookingSourceType; + +} + diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java new file mode 100644 index 0000000..e785111 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java @@ -0,0 +1,18 @@ +package moja.refrigerator.aggregate.recipe; + + +import jakarta.persistence.*; +import lombok.Data; + +@Table(name = "tbl_recipe_source_type") +@Entity +@Data +public class RecipeSourceType { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "cooking_source_type_pk") + private int cookingSourceTypePk; + + @Column(name = "cooking_source_type",length = 50) + private String cookingSourceType; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java new file mode 100644 index 0000000..262bd10 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java @@ -0,0 +1,23 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.ingredient.IngredientManagement; + +@Data +@Entity +@Table(name = "tbl_replacable_ingredient") +public class ReplacableIngredient { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "replaceable_ingredient_pk") + private long ReplaceableIngredientPk ; + + @JoinColumn(name = "ingredient_management") + @ManyToOne + private IngredientManagement ingredientManagement; + + @JoinColumn(name = "recipe_ingredient") + @ManyToOne + private RecipeIngredient RecipeIngredient ; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java new file mode 100644 index 0000000..ce53d0b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -0,0 +1,17 @@ +package moja.refrigerator.controller.recipe; + +import moja.refrigerator.service.recipe.RecipeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/recipe") +public class RecipeController { + private RecipeService recipeService; + + @Autowired + public RecipeController(RecipeService recipeService) { + this.recipeService = recipeService; + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java new file mode 100644 index 0000000..28dc01e --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java @@ -0,0 +1,8 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.Recipe; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecipeRepository extends JpaRepository { +} + diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java new file mode 100644 index 0000000..ca44892 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -0,0 +1,4 @@ +package moja.refrigerator.service.recipe; + +public interface RecipeService { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java new file mode 100644 index 0000000..63d5c90 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -0,0 +1,20 @@ +package moja.refrigerator.service.recipe; + + +import moja.refrigerator.repository.recipe.RecipeRepository; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class RecipeServiceImpl implements RecipeService { + + private RecipeRepository recipeRepository; + private ModelMapper mapper; + + @Autowired + public RecipeServiceImpl(RecipeRepository recipeRepository, ModelMapper mapper) { + this.recipeRepository = recipeRepository; + this.mapper = mapper; + } +} \ No newline at end of file From e842e7c963aa92746271e525cc25603281a86458 Mon Sep 17 00:00:00 2001 From: mincheol Date: Tue, 10 Dec 2024 15:08:25 +0900 Subject: [PATCH 05/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20column=20?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95..=20(=EB=8C=80=EC=86=8C=EB=AC=B8?= =?UTF-8?q?=EC=9E=90)=201210?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aggregate/ingredient/IngredientCategory.java | 4 ++-- .../aggregate/ingredient/IngredientStorage.java | 4 ++-- .../java/moja/refrigerator/aggregate/recipe/Comment.java | 8 ++++---- .../refrigerator/aggregate/recipe/RecipeCategory.java | 2 +- .../moja/refrigerator/aggregate/recipe/RecipeSource.java | 4 ++-- .../aggregate/recipe/ReplacableIngredient.java | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java index 94f0113..56de8ce 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java @@ -11,8 +11,8 @@ public class IngredientCategory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ingredient_category_pk") - private int IngredientCategoryPk; + private int ingredientCategoryPk; @Column(name = "ingredient_category") - private String IngredientCategory; + private String ingredientCategory; } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java index 0413b68..2dc7828 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java @@ -10,8 +10,8 @@ public class IngredientStorage { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ingredient_storage_pk") - private int IngredientStoragePk; + private int ingredientStoragePk; @Column(name = "ingredient_storage") - private String IngredientStorage; + private String ingredientStorage; } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java index 21d300a..694fc8a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Comment.java @@ -11,14 +11,14 @@ public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "comment_pk") - private long CommentPk ; + private long commentPk ; @Column(name = "comment_create_time") - private String CommentCreateTime ; + private String commentCreateTime ; @Column(name = "comment_update_time") - private String CommentUpdateTime ; + private String commentUpdateTime ; @Column(name = "comment_contents") - private String CommentContents ; + private String commentContents ; @JoinColumn(name = "user") @ManyToOne diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java index 8fb98cd..c5561ea 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeCategory.java @@ -10,7 +10,7 @@ public class RecipeCategory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "recipe_category_pk") - private int RecipeCategoryPK; + private int recipeCategoryPK; @Column(name = "recipe_category") private String recipeCategory; diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 85c63ef..6f16f80 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -17,10 +17,10 @@ public class RecipeSource { private String cookingSourceSave; @Column(name = "cooking_source_create_time") - private String CookingSourceCreateTime; + private String cookingSourceCreateTime; @Column(name = "cooking_source_file_name") - private String CookingSourceFileName; + private String cookingSourceFileName; @JoinColumn(name = "cooking_source_type") @OneToOne diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java index 262bd10..260fc7b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/ReplacableIngredient.java @@ -11,7 +11,7 @@ public class ReplacableIngredient { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "replaceable_ingredient_pk") - private long ReplaceableIngredientPk ; + private long replaceableIngredientPk ; @JoinColumn(name = "ingredient_management") @ManyToOne @@ -19,5 +19,5 @@ public class ReplacableIngredient { @JoinColumn(name = "recipe_ingredient") @ManyToOne - private RecipeIngredient RecipeIngredient ; + private RecipeIngredient recipeIngredient ; } From cced5b8f904d66f81544cc4ab392080fa2f808b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Tue, 10 Dec 2024 17:28:07 +0900 Subject: [PATCH 06/46] =?UTF-8?q?=EC=9E=AC=EB=A3=8C=20=C3=AB=C3=A3=C2=84fe?= =?UTF-8?q?at:=20=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refrigerator/.idea/dataSources.xml | 19 ++++++++++++ .../ingredient/IngredientCategory.java | 4 +-- .../ingredient/IngredientStorage.java | 4 +-- .../ingredient/IngredientController.java | 8 +++++ .../request/IngredientCreateRequest.java | 14 +++++++++ .../IngredientCategoryRepository.java | 9 ++++++ .../IngredientManagementRepository.java | 3 ++ .../IngredientStorageRepository.java | 9 ++++++ .../service/ingredient/IngredientService.java | 3 ++ .../ingredient/IngredientServiceImpl.java | 30 +++++++++++++++++++ 10 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 refrigerator/.idea/dataSources.xml create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientCategoryRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientStorageRepository.java diff --git a/refrigerator/.idea/dataSources.xml b/refrigerator/.idea/dataSources.xml new file mode 100644 index 0000000..6ce6193 --- /dev/null +++ b/refrigerator/.idea/dataSources.xml @@ -0,0 +1,19 @@ + + + + + mysql.8 + true + true + $PROJECT_DIR$/src/main/resources/application.yml + com.mysql.cj.jdbc.Driver + jdbc:mysql://localhost:3306/refrigerator + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java index 94f0113..56de8ce 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientCategory.java @@ -11,8 +11,8 @@ public class IngredientCategory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ingredient_category_pk") - private int IngredientCategoryPk; + private int ingredientCategoryPk; @Column(name = "ingredient_category") - private String IngredientCategory; + private String ingredientCategory; } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java index 0413b68..2dc7828 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientStorage.java @@ -10,8 +10,8 @@ public class IngredientStorage { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ingredient_storage_pk") - private int IngredientStoragePk; + private int ingredientStoragePk; @Column(name = "ingredient_storage") - private String IngredientStorage; + private String ingredientStorage; } diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 94315c0..fabffb3 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -1,7 +1,10 @@ package moja.refrigerator.controller.ingredient; +import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -14,4 +17,9 @@ public class IngredientController { public IngredientController(IngredientService ingredientService) { this.ingredientService = ingredientService; } + + @PostMapping + public void createIngredient(@RequestBody IngredientCreateRequest request) { + ingredientService.createIngredient(request); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java new file mode 100644 index 0000000..ac63e4b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java @@ -0,0 +1,14 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class IngredientCreateRequest { + private String ingredientName; + private String expirationDate; + private String registrationDate; + private int seasonDate; + +// private int ingredientCategoryPk; +// private int ingredientStoragePk; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientCategoryRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientCategoryRepository.java new file mode 100644 index 0000000..6ff4511 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientCategoryRepository.java @@ -0,0 +1,9 @@ +package moja.refrigerator.repository.ingredient; + +import moja.refrigerator.aggregate.ingredient.IngredientCategory; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface IngredientCategoryRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java index c9619a4..7a6e9f3 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java @@ -2,6 +2,9 @@ import moja.refrigerator.aggregate.ingredient.IngredientManagement; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface IngredientManagementRepository extends JpaRepository { } + diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientStorageRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientStorageRepository.java new file mode 100644 index 0000000..67e6c36 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientStorageRepository.java @@ -0,0 +1,9 @@ +package moja.refrigerator.repository.ingredient; + +import moja.refrigerator.aggregate.ingredient.IngredientStorage; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface IngredientStorageRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 92b1ac0..419ec56 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -1,4 +1,7 @@ package moja.refrigerator.service.ingredient; +import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; + public interface IngredientService { + void createIngredient(IngredientCreateRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 8dd1aeb..db6d42a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -1,20 +1,50 @@ package moja.refrigerator.service.ingredient; +//import moja.refrigerator.aggregate.ingredient.IngredientCategory; +import moja.refrigerator.aggregate.ingredient.IngredientManagement; +//import moja.refrigerator.aggregate.ingredient.IngredientStorage; +import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +//import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; +//import moja.refrigerator.repository.ingredient.IngredientStorageRepository; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service public class IngredientServiceImpl implements IngredientService{ private IngredientManagementRepository ingredientManagementRepository; +// private IngredientStorageRepository ingredientStorageRepository; +// private IngredientCategoryRepository ingredientCategoryRepository; private ModelMapper mapper; @Autowired public IngredientServiceImpl(IngredientManagementRepository ingredientManagementRepository, +// IngredientStorageRepository ingredientStorageRepository, +// IngredientCategoryRepository ingredientCategoryRepository, ModelMapper mapper) { this.ingredientManagementRepository = ingredientManagementRepository; +// this.ingredientStorageRepository = ingredientStorageRepository; +// this.ingredientCategoryRepository = ingredientCategoryRepository; this.mapper = mapper; } + + @Override + @Transactional + public void createIngredient(IngredientCreateRequest request) { + IngredientManagement ingredient = mapper.map(request, IngredientManagement.class); + +// IngredientCategory category = ingredientCategoryRepository.findById(request.getIngredientCategoryPk()) +// .orElseThrow(() -> new IllegalArgumentException("카테고리를 찾을 수 없습니다.")); +// +// IngredientStorage storage = ingredientStorageRepository.findById(request.getIngredientStoragePk()) +// .orElseThrow(() -> new IllegalArgumentException("저장소를 찾을 수 없습니다.")); +// +// ingredient.setIngredientCategory(category); +// ingredient.setIngredientStorage(storage); + + ingredientManagementRepository.save(ingredient); + } } From fc1551a025a9a1217e0b200fbcc5cd1597e37d12 Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Wed, 11 Dec 2024 14:37:55 +0900 Subject: [PATCH 07/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=20=EC=A6=90?= =?UTF-8?q?=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. controller, repository, dto 생성 2. service 작성중 Related to: #03 --- .../aggregate/ingredient/IngredientBookmark.java | 4 ++-- .../ingredient/IngredientController.java | 14 ++++++++++++++ .../service/ingredient/IngredientService.java | 4 ++++ .../service/ingredient/IngredientServiceImpl.java | 12 ++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java index 5f7a32b..5140c88 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java @@ -15,10 +15,10 @@ public class IngredientBookmark { private long ingredientBookmarkPk; @ManyToOne - @JoinColumn(name = "user") + @JoinColumn(name = "user_pk") private User user; @ManyToOne - @JoinColumn(name = "ingredient_management") + @JoinColumn(name = "ingredient_management_pk") private IngredientManagement ingredientManagement; } diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index fabffb3..2164b70 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -1,8 +1,12 @@ package moja.refrigerator.controller.ingredient; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,4 +26,14 @@ public IngredientController(IngredientService ingredientService) { public void createIngredient(@RequestBody IngredientCreateRequest request) { ingredientService.createIngredient(request); } + + @PostMapping("/bookmark/regist") + public ResponseEntity createIngredientBookmark( + @RequestBody RequestRegistIngredientBookmark requestBookmark + ) { + ResponseRegistIngredientBookmark responseBookmark = + ingredientService.createIngredientBookmark(requestBookmark); + + return ResponseEntity.status(HttpStatus.CREATED).body(responseBookmark); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 419ec56..43b5479 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -1,7 +1,11 @@ package moja.refrigerator.service.ingredient; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; public interface IngredientService { void createIngredient(IngredientCreateRequest request); + + ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIngredientBookmark requestBookmark); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index db6d42a..75eb3d7 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -5,6 +5,9 @@ //import moja.refrigerator.aggregate.ingredient.IngredientStorage; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; //import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; +import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; +import moja.refrigerator.repository.ingredient.IngredientBookmarkRepository; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; //import moja.refrigerator.repository.ingredient.IngredientStorageRepository; import org.modelmapper.ModelMapper; @@ -18,16 +21,19 @@ public class IngredientServiceImpl implements IngredientService{ private IngredientManagementRepository ingredientManagementRepository; // private IngredientStorageRepository ingredientStorageRepository; // private IngredientCategoryRepository ingredientCategoryRepository; + private IngredientBookmarkRepository ingredientBookmarkRepository; private ModelMapper mapper; @Autowired public IngredientServiceImpl(IngredientManagementRepository ingredientManagementRepository, // IngredientStorageRepository ingredientStorageRepository, // IngredientCategoryRepository ingredientCategoryRepository, + IngredientBookmarkRepository ingredientBookmarkRepository, ModelMapper mapper) { this.ingredientManagementRepository = ingredientManagementRepository; // this.ingredientStorageRepository = ingredientStorageRepository; // this.ingredientCategoryRepository = ingredientCategoryRepository; + this.ingredientBookmarkRepository = ingredientBookmarkRepository; this.mapper = mapper; } @@ -47,4 +53,10 @@ public void createIngredient(IngredientCreateRequest request) { ingredientManagementRepository.save(ingredient); } + + @Override + public ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIngredientBookmark requestBookmark) { + + return new ResponseRegistIngredientBookmark(); + } } From d0ece5333b3eb2c8555c32668498b9a38358ea93 Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Wed, 11 Dec 2024 14:38:01 +0900 Subject: [PATCH 08/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=20=EC=A6=90?= =?UTF-8?q?=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. controller, repository, dto 생성 2. service 작성중 Related to: #03 --- .../request/RequestRegistIngredientBookmark.java | 9 +++++++++ .../response/ResponseRegistIngredientBookmark.java | 7 +++++++ .../ingredient/IngredientBookmarkRepository.java | 7 +++++++ 3 files changed, 23 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java new file mode 100644 index 0000000..a7690f8 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java @@ -0,0 +1,9 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class RequestRegistIngredientBookmark { + private int userPk; + private int ingredientPk; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java new file mode 100644 index 0000000..cfa2d4d --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java @@ -0,0 +1,7 @@ +package moja.refrigerator.dto.ingredient.response; + +import lombok.Data; + +@Data +public class ResponseRegistIngredientBookmark { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java new file mode 100644 index 0000000..90c2e54 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java @@ -0,0 +1,7 @@ +package moja.refrigerator.repository.ingredient; + +import moja.refrigerator.aggregate.ingredient.IngredientBookmark; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface IngredientBookmarkRepository extends JpaRepository { +} From c778f4b1031d56674b2b946498313e90c9ce548d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Wed, 11 Dec 2024 16:07:32 +0900 Subject: [PATCH 09/46] =?UTF-8?q?#1=20=EC=9E=AC=EB=A3=8C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ingredient/IngredientController.java | 15 ++++++++---- .../response/IngredientResponse.java | 24 +++++++++++++++++++ .../service/ingredient/IngredientService.java | 6 ++++- .../ingredient/IngredientServiceImpl.java | 16 +++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index fabffb3..0e821ac 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -1,12 +1,12 @@ package moja.refrigerator.controller.ingredient; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController @RequestMapping("/ingredient") @@ -18,8 +18,15 @@ public IngredientController(IngredientService ingredientService) { this.ingredientService = ingredientService; } + // 재료 등록 @PostMapping public void createIngredient(@RequestBody IngredientCreateRequest request) { ingredientService.createIngredient(request); } + + // 재료 조회 + @GetMapping + public List getIngredient() { + return ingredientService.getIngredient(); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java new file mode 100644 index 0000000..a98038f --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java @@ -0,0 +1,24 @@ +package moja.refrigerator.dto.ingredient.response; + +import lombok.Data; + +@Data +public class IngredientResponse { + private long ingredientManagementPk; + private String ingredientName; + private String expirationDate; + private String registrationDate; + private int seasonDate; + + // ModelMapper를 위한 기본 생성자 생성 + public IngredientResponse() {} + + // 생성자 + public IngredientResponse(long ingredientManagementPk, String ingredientName, String expirationDate, String registrationDate, int seasonDate) { + this.ingredientManagementPk = ingredientManagementPk; + this.ingredientName = ingredientName; + this.expirationDate = expirationDate; + this.registrationDate = registrationDate; + this.seasonDate = seasonDate; + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 419ec56..45d10c0 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -1,7 +1,11 @@ package moja.refrigerator.service.ingredient; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; + +import java.util.List; public interface IngredientService { - void createIngredient(IngredientCreateRequest request); + void createIngredient(IngredientCreateRequest request); // 재료 등록 메서드 + List getIngredient(); // 재료 조회 메서드 } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index db6d42a..92465ca 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -5,6 +5,7 @@ //import moja.refrigerator.aggregate.ingredient.IngredientStorage; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; //import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; //import moja.refrigerator.repository.ingredient.IngredientStorageRepository; import org.modelmapper.ModelMapper; @@ -12,6 +13,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.stream.Collectors; + @Service public class IngredientServiceImpl implements IngredientService{ @@ -45,6 +49,18 @@ public void createIngredient(IngredientCreateRequest request) { // ingredient.setIngredientCategory(category); // ingredient.setIngredientStorage(storage); + // 재료를 JpaRepository의 save() 메소드로 DB에 저장 ! ingredientManagementRepository.save(ingredient); } + + @Override + @Transactional(readOnly = true) + public List getIngredient() { + List ingredients = ingredientManagementRepository.findAll(); + + return ingredients.stream() + .map(ingredient -> mapper.map(ingredient, IngredientResponse.class)) + .collect(Collectors.toList()); + } + } From e7cf93ebdaa3f7007c1024d606d2b6a8af56560d Mon Sep 17 00:00:00 2001 From: mincheol Date: Wed, 11 Dec 2024 18:36:21 +0900 Subject: [PATCH 10/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=ED=95=9C?= =?UTF-8?q?=20=EC=9D=BC=20:=201.=20cooking=5Fsource=20->=20recipe=5Fsource?= =?UTF-8?q?=20=EB=A1=9C=20=EC=9D=BC=EA=B4=84=20=EB=B3=80=EA=B2=BD.=202.=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9A=A9=20Category,=20Repository,=20Request?= =?UTF-8?q?,=20=EC=B6=94=EA=B0=80=203.=20=EC=9D=BD=EA=B8=B0=20=EC=9A=A9=20?= =?UTF-8?q?Repository,=20response=20=EC=B6=94=EA=B0=80=204.=20UserDummyRep?= =?UTF-8?q?ository=20=EC=83=9D=EC=84=B1=205.=20=EC=9E=84=EC=8B=9C=20recipe?= =?UTF-8?q?=5Fsource=5Ftype,=20recipe=5Fsource=5Fcategory=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 문제점 : 1. recipe에 recipe 적을 란이 없다. 2. RecipeCreateTime이 저장되는데 format을 안된다. 해야할 일 : 1. 문제점 수정 2. UD 생성 --- refrigerator/.idea/dataSources.xml | 6 +- .../refrigerator/aggregate/recipe/Recipe.java | 18 ++++-- .../aggregate/recipe/RecipeSource.java | 22 +++---- .../aggregate/recipe/RecipeSourceType.java | 8 +-- .../controller/recipe/RecipeController.java | 18 +++++- .../recipe/request/RecipeCreateRequest.java | 22 +++++++ .../request/RecipeSourceCreateRequest.java | 15 +++++ .../dto/recipe/response/RecipeResponse.java | 23 ++++++++ .../recipe/RecipeCategoryRepositoy.java | 10 ++++ .../repository/recipe/RecipeRepository.java | 2 + .../recipe/RecipeSourceRepository.java | 7 +++ .../repository/user/UserRepository.java | 7 +++ .../service/recipe/RecipeService.java | 10 ++++ .../service/recipe/RecipeServiceImpl.java | 58 ++++++++++++++++++- 14 files changed, 201 insertions(+), 25 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeSourceCreateRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java diff --git a/refrigerator/.idea/dataSources.xml b/refrigerator/.idea/dataSources.xml index 6ce6193..acfaa41 100644 --- a/refrigerator/.idea/dataSources.xml +++ b/refrigerator/.idea/dataSources.xml @@ -1,13 +1,11 @@ - + mysql.8 true - true - $PROJECT_DIR$/src/main/resources/application.yml com.mysql.cj.jdbc.Driver - jdbc:mysql://localhost:3306/refrigerator + jdbc:mysql://localhost:3306 diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index aa32223..fdac2ea 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -1,8 +1,13 @@ package moja.refrigerator.aggregate.recipe; +import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.*; import lombok.Data; import moja.refrigerator.aggregate.user.User; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.time.LocalDateTime; @Data @Entity @@ -20,23 +25,28 @@ public class Recipe { @Column(name = "recipe_cooking_time") private int recipeCookingTime; + + @CreationTimestamp @Column(name = "recipe_create_time") - private String recipeCreateTime; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul") + private LocalDateTime recipeCreateTime; + @UpdateTimestamp @Column(name = "recipe_update_time") - private String recipeUpdateTime; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul") + private LocalDateTime recipeUpdateTime; @Column(name = "recipe_difficulty") private int recipeDifficulty; @Column(name = "recipe_views") - private long recipeViews; + private long recipeViews = 0; @JoinColumn(name = "user") @ManyToOne private User user; - @JoinColumn(name = "cooking_source") + @JoinColumn(name = "recipe_source") @ManyToOne private RecipeSource recipeSource; diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 6f16f80..8750ffd 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -4,27 +4,29 @@ import jakarta.persistence.*; import lombok.Data; +import java.time.LocalDateTime; + @Data @Entity @Table(name="tbl_recipe_source") public class RecipeSource { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "cooking_source_pk") - private long cookingSourcePk; + @Column(name = "recipe_source_pk") + private long recipeSourcePk; - @Column(name = "cooking_source_save") - private String cookingSourceSave; + @Column(name = "recipe_source_save") + private String recipeSourceSave; - @Column(name = "cooking_source_create_time") - private String cookingSourceCreateTime; + @Column(name = "recipe_source_create_time") + private String recipeSourceCreateTime = LocalDateTime.now().toString(); - @Column(name = "cooking_source_file_name") - private String cookingSourceFileName; + @Column(name = "recipe_source_file_name") + private String recipeSourceFileName; - @JoinColumn(name = "cooking_source_type") + @JoinColumn(name = "recipe_source_type") @OneToOne - private RecipeSourceType cookingSourceType; + private RecipeSourceType recipeSourceType; } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java index e785111..8ace140 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java @@ -10,9 +10,9 @@ public class RecipeSourceType { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "cooking_source_type_pk") - private int cookingSourceTypePk; + @Column(name = "recipe_source_type_pk") + private int recipeSourceTypePk; - @Column(name = "cooking_source_type",length = 50) - private String cookingSourceType; + @Column(name = "recipe_source_type",length = 50) + private String recipeSourceType; } diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index ce53d0b..69971e9 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -1,9 +1,13 @@ package moja.refrigerator.controller.recipe; +import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController @RequestMapping("/recipe") @@ -14,4 +18,14 @@ public class RecipeController { public RecipeController(RecipeService recipeService) { this.recipeService = recipeService; } + + @PostMapping + public void createRecipe(@RequestBody RecipeCreateRequest request){ + recipeService.createRecipe(request); + } + + @GetMapping + public List getAllRecipes(){ + return recipeService.getAllRecipes(); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java new file mode 100644 index 0000000..cf56252 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java @@ -0,0 +1,22 @@ +package moja.refrigerator.dto.recipe.request; + +import lombok.Data; +import moja.refrigerator.aggregate.recipe.RecipeCategory; +import moja.refrigerator.aggregate.recipe.RecipeSource; +import moja.refrigerator.aggregate.user.User; + +@Data +public class RecipeCreateRequest { + private String recipeName; + private int recipeCookingTime; + private int recipeDifficulty; + + private String recipeSource; + private String recipeCategory; + private String userPk; + +// private long recipePk; // 자동 추가 +// private String recipeCreateTime; //자동 추가 +// private String recipeUpdateTime; //자동 추가 +// private long recipeViews; // 조회 시 올리는 것으로 +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeSourceCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeSourceCreateRequest.java new file mode 100644 index 0000000..68b71d4 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeSourceCreateRequest.java @@ -0,0 +1,15 @@ +package moja.refrigerator.dto.recipe.request; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.recipe.RecipeSourceType; + +@Data +public class RecipeSourceCreateRequest { + private String recipeSourceFileName; + private String recipeSourceSave; + private RecipeSourceType recipeSourceType; + +// private long recipeSourcePk; +// private String recipeSourceCreateTime; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java new file mode 100644 index 0000000..73d7888 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java @@ -0,0 +1,23 @@ +package moja.refrigerator.dto.recipe.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class RecipeResponse { + + private long recipePk; + private String recipeName; + private int recipeCookingTime; + private int recipeDifficulty; + private long recipeViews; + + private LocalDateTime recipeCreateTime;; + private LocalDateTime recipeUpdateTime; + + private String recipeSource; + private String userPk; + private String recipeCategory; + +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java new file mode 100644 index 0000000..e3a435a --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java @@ -0,0 +1,10 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.RecipeCategory; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RecipeCategoryRepositoy extends JpaRepository { + +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java index 28dc01e..29b436a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java @@ -2,7 +2,9 @@ import moja.refrigerator.aggregate.recipe.Recipe; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface RecipeRepository extends JpaRepository { } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java new file mode 100644 index 0000000..bdcf4d0 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java @@ -0,0 +1,7 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.RecipeSource; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecipeSourceRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java new file mode 100644 index 0000000..f24e3d5 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -0,0 +1,7 @@ +package moja.refrigerator.repository.user; + +import moja.refrigerator.aggregate.user.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository{ +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index ca44892..abc8532 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -1,4 +1,14 @@ package moja.refrigerator.service.recipe; +import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.response.RecipeResponse; +import moja.refrigerator.repository.recipe.RecipeRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + public interface RecipeService { + void createRecipe(RecipeCreateRequest request); + List getAllRecipes(); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index 63d5c90..f358ca8 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -1,20 +1,76 @@ package moja.refrigerator.service.recipe; +import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.aggregate.recipe.RecipeCategory; +import moja.refrigerator.aggregate.recipe.RecipeSource; +import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.response.RecipeResponse; +import moja.refrigerator.repository.recipe.RecipeCategoryRepositoy; import moja.refrigerator.repository.recipe.RecipeRepository; +import moja.refrigerator.repository.recipe.RecipeSourceRepository; +import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; +import org.modelmapper.PropertyMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; @Service public class RecipeServiceImpl implements RecipeService { private RecipeRepository recipeRepository; + private UserRepository userRepository; + private RecipeSourceRepository recipeSourceRepository; + private RecipeCategoryRepositoy recipeCategoryRepositoy; private ModelMapper mapper; @Autowired - public RecipeServiceImpl(RecipeRepository recipeRepository, ModelMapper mapper) { + public RecipeServiceImpl( + RecipeRepository recipeRepository, + ModelMapper mapper, + RecipeSourceRepository recipeSourceRepository, + UserRepository userRepository, + RecipeCategoryRepositoy recipeCategoryRepositoy + ) { this.recipeRepository = recipeRepository; this.mapper = mapper; + this.recipeSourceRepository = recipeSourceRepository; + this.userRepository = userRepository; + this.recipeCategoryRepositoy = recipeCategoryRepositoy; } + + @Override + @Transactional + public void createRecipe(RecipeCreateRequest request) { + + Recipe recipe = mapper.map(request, Recipe.class); + +// //User 조회 +// User user = userRepository.findById(request.getUserId) +// .orElseThrow(IllegalArgumentException::new); +// recipe.setUserPk(user); + +// //RecipeSource 조회 +// RecipeSource recipeSource = recipeSourceRepository.findById(request.getRecipeSource()) +// .orElseThrow(IllegalArgumentException::new); +// recipe.setRecipeSource(recipeSource); + + //RecipeCategory +// RecipeCategory recipeCategory = .findById(request.getRecipeCategory()) +// .orElseThrow(IllegalArgumentException::new); +// recipe.setRecipeCategory(recipeCategory); + + recipeRepository.save(recipe); + } + + @Override + public List getAllRecipes(){ + return recipeRepository.findAll().stream() + .map(recipe -> mapper.map(recipe, RecipeResponse.class)) + .collect(Collectors.toList()); + }; } \ No newline at end of file From 413b3d788b475bbb4baed00a4c6abdd574277c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Thu, 12 Dec 2024 00:20:34 +0900 Subject: [PATCH 11/46] =?UTF-8?q?Initial:=20=ED=9A=8C=EC=9B=90=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Spring Security 의존성 추가 - JWT 관련 의존성 추가 (jjwt-api, jjwt-impl, jjwt-jackson) - SecurityConfig 클래스 구성 - User 엔티티 정의 - Controller, Service, Repository 계층 구조 설정 Resolves: #11 --- refrigerator/build.gradle | 6 +++ .../refrigerator/aggregate/user/User.java | 22 +++++++++ .../refrigerator/config/SecurityConfig.java | 48 +++++++++++++++++++ .../controller/user/AdminController.java | 12 +++++ .../controller/user/UserController.java | 19 ++++++++ .../repository/user/UserRepository.java | 9 ++++ .../service/user/UserService.java | 4 ++ .../service/user/UserServiceImpl.java | 16 +++++++ 8 files changed, 136 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/controller/user/AdminController.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java diff --git a/refrigerator/build.gradle b/refrigerator/build.gradle index d1f5710..0e3a358 100644 --- a/refrigerator/build.gradle +++ b/refrigerator/build.gradle @@ -35,6 +35,12 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.modelmapper:modelmapper:3.1.0' + + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'io.jsonwebtoken:jjwt-api:0.12.3' + implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' + implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' + testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java index a352fc0..4fcd923 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java @@ -2,6 +2,9 @@ import jakarta.persistence.*; import lombok.Data; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDate; @Entity @Table(name = "tbl_user") @@ -11,4 +14,23 @@ public class User { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_pk") private long userPk; + + @Column(name = "user_id", nullable = false, unique = true) + private String userId; + + @Column(name = "user_pw", nullable = false) + private String userPw; + + @Column(name = "user_email", nullable = false, unique = true) + private String userEmail; + + @Column(name = "user_nickname", nullable = false, unique = true) + private String userNickname; + + @Column(name = "join_date", nullable = false, updatable = false) + @CreationTimestamp + private LocalDate joinDate; + +// @Column(name = "leave_date") +// private LocalDate leaveDate; } diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java new file mode 100644 index 0000000..17e66a6 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -0,0 +1,48 @@ +package moja.refrigerator.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + @Bean + // 비밀번호 암호화를 위한 인코더 + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + // csrf 보안 비활성화 + http + .csrf((auth) -> auth.disable()); + + // 기본 로그인 폼 비활성화 + http + .formLogin((auth) -> auth.disable()); + + // HTTP Basic 인증 비활성화 + http + .httpBasic((auth) -> auth.disable()); + + // URL 별 접근 권한 설정 + http + .authorizeHttpRequests((auth) -> auth + .requestMatchers("/login", "/", "/join").permitAll() // 이 경로들은 모두 접근 가능 + .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 + .anyRequest().authenticated()); // 나머지는 인증된 사용자만 + + // 세션 관리 설정 + http + .sessionManagement((session) -> session + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); // JWT 사용을 위한 세션리스 설정 + + return http.build(); + } +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/AdminController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/AdminController.java new file mode 100644 index 0000000..f88b295 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/AdminController.java @@ -0,0 +1,12 @@ +package moja.refrigerator.controller.user; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class AdminController { + @GetMapping("/admin") + public String getAdminPage() { + return "admin Controller"; + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java new file mode 100644 index 0000000..bfb9c12 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -0,0 +1,19 @@ +package moja.refrigerator.controller.user; + +import moja.refrigerator.service.user.UserService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class UserController { + private final UserService userService; + + public UserController(UserService userService) { + this.userService = userService; + } + +// @GetMapping("/") +// public String getMainPage() { +// return "user Controller"; +// } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java new file mode 100644 index 0000000..38fa297 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -0,0 +1,9 @@ +package moja.refrigerator.repository.user; + +import moja.refrigerator.aggregate.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java new file mode 100644 index 0000000..3ebab0e --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java @@ -0,0 +1,4 @@ +package moja.refrigerator.service.user; + +public interface UserService { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java new file mode 100644 index 0000000..4413f85 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -0,0 +1,16 @@ +package moja.refrigerator.service.user; + +import moja.refrigerator.repository.user.UserRepository; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl implements UserService { + private final UserRepository userRepository; + private final BCryptPasswordEncoder passwordEncoder; + + public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + } +} From d125471b449cfe5c4d52ea947e9af6c424b330fe Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Thu, 12 Dec 2024 15:58:54 +0900 Subject: [PATCH 12/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=20=EC=A6=90?= =?UTF-8?q?=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 재료 즐겨찾기 등록 Resolves: #03 --- .../RequestRegistIngredientBookmark.java | 4 +-- .../ResponseRegistIngredientBookmark.java | 6 +++++ .../repository/user/UserRepository.java | 7 ++++++ .../ingredient/IngredientServiceImpl.java | 25 ++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java index a7690f8..33c0ccf 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java @@ -4,6 +4,6 @@ @Data public class RequestRegistIngredientBookmark { - private int userPk; - private int ingredientPk; + private long userPk; + private long ingredientPk; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java index cfa2d4d..41c5dab 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java @@ -1,7 +1,13 @@ package moja.refrigerator.dto.ingredient.response; import lombok.Data; +import moja.refrigerator.aggregate.ingredient.IngredientBookmark; +import moja.refrigerator.aggregate.ingredient.IngredientManagement; +import moja.refrigerator.aggregate.user.User; @Data public class ResponseRegistIngredientBookmark { + private long ingredientBookmarkPk; + private User user; + private IngredientManagement ingredientManagement; } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java new file mode 100644 index 0000000..89c3e97 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -0,0 +1,7 @@ +package moja.refrigerator.repository.user; + +import moja.refrigerator.aggregate.user.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 75eb3d7..4a3983c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -1,8 +1,11 @@ package moja.refrigerator.service.ingredient; //import moja.refrigerator.aggregate.ingredient.IngredientCategory; +import jakarta.persistence.EntityNotFoundException; +import moja.refrigerator.aggregate.ingredient.IngredientBookmark; import moja.refrigerator.aggregate.ingredient.IngredientManagement; //import moja.refrigerator.aggregate.ingredient.IngredientStorage; +import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; //import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; @@ -10,7 +13,9 @@ import moja.refrigerator.repository.ingredient.IngredientBookmarkRepository; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; //import moja.refrigerator.repository.ingredient.IngredientStorageRepository; +import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; +import org.modelmapper.convention.MatchingStrategies; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,6 +27,7 @@ public class IngredientServiceImpl implements IngredientService{ // private IngredientStorageRepository ingredientStorageRepository; // private IngredientCategoryRepository ingredientCategoryRepository; private IngredientBookmarkRepository ingredientBookmarkRepository; + private UserRepository userRepository; private ModelMapper mapper; @Autowired @@ -29,11 +35,13 @@ public IngredientServiceImpl(IngredientManagementRepository ingredientManagement // IngredientStorageRepository ingredientStorageRepository, // IngredientCategoryRepository ingredientCategoryRepository, IngredientBookmarkRepository ingredientBookmarkRepository, + UserRepository userRepository, ModelMapper mapper) { this.ingredientManagementRepository = ingredientManagementRepository; // this.ingredientStorageRepository = ingredientStorageRepository; // this.ingredientCategoryRepository = ingredientCategoryRepository; this.ingredientBookmarkRepository = ingredientBookmarkRepository; + this.userRepository = userRepository; this.mapper = mapper; } @@ -56,7 +64,22 @@ public void createIngredient(IngredientCreateRequest request) { @Override public ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIngredientBookmark requestBookmark) { + User user = userRepository.findById(requestBookmark.getUserPk()) + .orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다.")); - return new ResponseRegistIngredientBookmark(); + IngredientManagement ingredientManagement = ingredientManagementRepository + .findById(requestBookmark.getIngredientPk()) + .orElseThrow(() -> new EntityNotFoundException("재료를 찾을 수 없습니다.")); + + IngredientBookmark ingredientBookmark = new IngredientBookmark(); + + ingredientBookmark.setUser(user); + ingredientBookmark.setIngredientManagement(ingredientManagement); + + ingredientBookmarkRepository.save(ingredientBookmark); + + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + + return mapper.map(ingredientBookmark, ResponseRegistIngredientBookmark.class); } } From b40c0545dd5998069dfc453a302d6f525fc5e187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Thu, 12 Dec 2024 17:59:48 +0900 Subject: [PATCH 13/46] =?UTF-8?q?Feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /auth/join 경로로 POST 요청 - 아이디 / 이메일 / 닉네임 중복 검사 - 중복 검사 통과 시 User 테이블에 데이터 저장 - 이때, 비밀번호는 암호화하여 저장 Resolves: #13 --- .../refrigerator/config/SecurityConfig.java | 2 +- .../controller/user/UserController.java | 9 ++++ .../dto/user/request/UserCreateRequest.java | 11 +++++ .../exception/common/BusinessException.java | 7 +++ .../handler/GlobalExceptionHandler.java | 16 +++++++ .../user/DuplicateUserException.java | 9 ++++ .../repository/user/UserRepository.java | 3 ++ .../service/user/UserService.java | 3 ++ .../service/user/UserServiceImpl.java | 44 ++++++++++++++++++- 9 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserCreateRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/exception/common/BusinessException.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/exception/handler/GlobalExceptionHandler.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/exception/user/DuplicateUserException.java diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 17e66a6..0449c5e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -34,7 +34,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // URL 별 접근 권한 설정 http .authorizeHttpRequests((auth) -> auth - .requestMatchers("/login", "/", "/join").permitAll() // 이 경로들은 모두 접근 가능 + .requestMatchers("/auth/**").permitAll() // 이 경로들은 모두 접근 가능 .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index bfb9c12..324055a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -1,7 +1,10 @@ package moja.refrigerator.controller.user; +import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.service.user.UserService; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @@ -16,4 +19,10 @@ public UserController(UserService userService) { // public String getMainPage() { // return "user Controller"; // } + + // 회원 가입 처리 + @PostMapping("/auth/join") + public void joinProcess(@RequestBody UserCreateRequest request) { + userService.createUser(request); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserCreateRequest.java new file mode 100644 index 0000000..de6ebb5 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserCreateRequest.java @@ -0,0 +1,11 @@ +package moja.refrigerator.dto.user.request; + +import lombok.Data; + +@Data +public class UserCreateRequest { + private String userId; + private String userPw; + private String userEmail; + private String userNickname; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/exception/common/BusinessException.java b/refrigerator/src/main/java/moja/refrigerator/exception/common/BusinessException.java new file mode 100644 index 0000000..e012311 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/exception/common/BusinessException.java @@ -0,0 +1,7 @@ +package moja.refrigerator.exception.common; + +public class BusinessException extends RuntimeException { + public BusinessException(String message) { + super(message); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/exception/handler/GlobalExceptionHandler.java b/refrigerator/src/main/java/moja/refrigerator/exception/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..445d8e1 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/exception/handler/GlobalExceptionHandler.java @@ -0,0 +1,16 @@ +package moja.refrigerator.exception.handler; + +import moja.refrigerator.exception.user.DuplicateUserException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(DuplicateUserException.class) + public ResponseEntity handleDuplicateUser(DuplicateUserException e) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body(e.getMessage()); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/exception/user/DuplicateUserException.java b/refrigerator/src/main/java/moja/refrigerator/exception/user/DuplicateUserException.java new file mode 100644 index 0000000..b9937bf --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/exception/user/DuplicateUserException.java @@ -0,0 +1,9 @@ +package moja.refrigerator.exception.user; + +import moja.refrigerator.exception.common.BusinessException; + +public class DuplicateUserException extends BusinessException { + public DuplicateUserException(String message) { + super(message); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java index 38fa297..04cb76c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -6,4 +6,7 @@ @Repository public interface UserRepository extends JpaRepository { + boolean existsByUserId(String userId); + boolean existsByUserEmail(String userEmail); + boolean existsByUserNickname(String userNickname); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java index 3ebab0e..80fa52c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java @@ -1,4 +1,7 @@ package moja.refrigerator.service.user; +import moja.refrigerator.dto.user.request.UserCreateRequest; + public interface UserService { + void createUser(UserCreateRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 4413f85..21ff0bd 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -1,16 +1,58 @@ package moja.refrigerator.service.user; +import moja.refrigerator.aggregate.user.User; +import moja.refrigerator.dto.user.request.UserCreateRequest; +import moja.refrigerator.exception.user.DuplicateUserException; import moja.refrigerator.repository.user.UserRepository; +import org.modelmapper.ModelMapper; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; @Service public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final BCryptPasswordEncoder passwordEncoder; + private final ModelMapper modelMapper; - public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) { + public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; + this.modelMapper = modelMapper; + } + + @Override + @Transactional + public void createUser(UserCreateRequest request) { + // 중복 검사 로직 + checkDuplicateUser(request); + + // dto -> 엔티티 변환 + User user = modelMapper.map(request, User.class); + + // 비밀번호 암호화 + user.setUserPw(passwordEncoder.encode(request.getUserPw())); + + userRepository.save(user); + } + + private void checkDuplicateUser(UserCreateRequest request) { + List errors = new ArrayList<>(); + if (userRepository.existsByUserId(request.getUserId())) { + errors.add("이미 사용 중인 아이디입니다."); + } + if (userRepository.existsByUserEmail(request.getUserEmail())) { + errors.add("이미 사용 중인 이메일입니다."); + } + if (userRepository.existsByUserNickname(request.getUserNickname())) { + errors.add("이미 사용 중인 닉네임입니다."); + } + + if (!errors.isEmpty()) { + throw new DuplicateUserException(String.join(", ", errors)); + } } } From a1293458f35228c72d9d9fdb34d6f881907ee6d9 Mon Sep 17 00:00:00 2001 From: mincheol Date: Thu, 12 Dec 2024 19:27:45 +0900 Subject: [PATCH 14/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=ED=95=9C?= =?UTF-8?q?=20=EC=9D=BC=20:=201.=20Recipe=20Update,=20delete=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EB=AC=B8=EC=A0=9C=EC=A0=90=20:=20(=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4)=201.=20recipe=EC=97=90=20recipe=20=EC=A0=81=EC=9D=84?= =?UTF-8?q?=20=EB=9E=80=EC=9D=B4=20=EC=97=86=EB=8B=A4.=202.=20RecipeCreate?= =?UTF-8?q?Time=EC=9D=B4=20=EC=A0=80=EC=9E=A5=EB=90=98=EB=8A=94=EB=8D=B0?= =?UTF-8?q?=20format=EC=9D=84=20=EC=95=88=EB=90=9C=EB=8B=A4.=20(=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EB=AC=B8=EC=A0=9C=EC=A0=90)=20=20?= =?UTF-8?q?=EC=97=86=EC=9D=8C.=20=EC=95=9E=EC=84=9C=20=EB=A7=90=ED=95=9C?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=ED=95=B4=EC=95=BC=20?= =?UTF-8?q?=EB=82=98=EB=A8=B8=EC=A7=80=20=EC=A7=84=ED=96=89=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5.=20=ED=95=B4=EC=95=BC=ED=95=A0=20=EC=9D=BC=20:=201.?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=EC=A0=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/recipe/RecipeController.java | 11 ++++++++ .../recipe/request/RecipeUpdateRequest.java | 17 ++++++++++++ .../recipe/RecipeCategoryRepositoy.java | 4 ++- .../repository/recipe/RecipeRepository.java | 3 +++ .../recipe/RecipeSourceRepository.java | 3 +++ .../service/recipe/RecipeService.java | 3 +++ .../service/recipe/RecipeServiceImpl.java | 26 +++++++++++++++++++ 7 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeUpdateRequest.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index 69971e9..3bb64af 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -2,6 +2,7 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; import org.springframework.beans.factory.annotation.Autowired; @@ -28,4 +29,14 @@ public void createRecipe(@RequestBody RecipeCreateRequest request){ public List getAllRecipes(){ return recipeService.getAllRecipes(); } + + @DeleteMapping + public void deleteRecipe(@RequestParam long recipePk){ + recipeService.deleteRecipe(recipePk); + } + + @PutMapping + public void updateRecipe(@RequestBody RecipeUpdateRequest request){ + recipeService.updateRecipe(request); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeUpdateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeUpdateRequest.java new file mode 100644 index 0000000..dd7c2d9 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeUpdateRequest.java @@ -0,0 +1,17 @@ +package moja.refrigerator.dto.recipe.request; + + +import lombok.Data; + +@Data +public class RecipeUpdateRequest { + private long recipePk; + private String recipeName; + private int recipeCookingTime; + private int recipeDifficulty; + + private String recipeSource; + private String recipeCategory; + private String userPk; + +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java index e3a435a..280d996 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java @@ -4,7 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface RecipeCategoryRepositoy extends JpaRepository { - + Optional findByRecipeCategory(String RecipeCategory); } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java index 29b436a..aa514db 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeRepository.java @@ -4,7 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface RecipeRepository extends JpaRepository { + Optional findByRecipePk(long recipePk); } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java index bdcf4d0..d0db45e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceRepository.java @@ -3,5 +3,8 @@ import moja.refrigerator.aggregate.recipe.RecipeSource; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface RecipeSourceRepository extends JpaRepository { + Optional findByRecipeSourceFileName(String recipeSourceFileName); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index abc8532..4d6c154 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -2,6 +2,7 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeRepository; import org.springframework.stereotype.Service; @@ -11,4 +12,6 @@ public interface RecipeService { void createRecipe(RecipeCreateRequest request); List getAllRecipes(); + void deleteRecipe(long recipePk); + void updateRecipe(RecipeUpdateRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index f358ca8..b857df7 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -5,6 +5,7 @@ import moja.refrigerator.aggregate.recipe.RecipeCategory; import moja.refrigerator.aggregate.recipe.RecipeSource; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeCategoryRepositoy; import moja.refrigerator.repository.recipe.RecipeRepository; @@ -73,4 +74,29 @@ public List getAllRecipes(){ .map(recipe -> mapper.map(recipe, RecipeResponse.class)) .collect(Collectors.toList()); }; + + @Override + public void deleteRecipe(long recipePk) { + Recipe recipe = recipeRepository.findByRecipePk(recipePk) + .orElseThrow(IllegalArgumentException::new); + recipeRepository.delete(recipe); + } + + @Override + @Transactional + public void updateRecipe(RecipeUpdateRequest request) { + Recipe recipe = recipeRepository.findByRecipePk(request.getRecipePk()) + .orElseThrow(IllegalArgumentException::new); + + if (request.getRecipeName() != null) recipe.setRecipeName(request.getRecipeName()); + if (request.getRecipeCookingTime() != 0) recipe.setRecipeCookingTime(request.getRecipeCookingTime()); + if (request.getRecipeDifficulty() != 0) recipe.setRecipeDifficulty(request.getRecipeDifficulty()); + if (request.getRecipeSource() != null) recipe.setRecipeSource(recipeSourceRepository.findByRecipeSourceFileName(request.getRecipeSource()) + .orElseThrow(IllegalArgumentException::new)); + if (request.getRecipeCategory() != null) recipe.setRecipeCategory(recipeCategoryRepositoy.findByRecipeCategory(request.getRecipeCategory()) + .orElseThrow(IllegalArgumentException::new)); + + recipeRepository.save(recipe); + + } } \ No newline at end of file From 109c1f367b8c8316f3aa02304dbdd41391917d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Thu, 12 Dec 2024 19:34:29 +0900 Subject: [PATCH 15/46] =?UTF-8?q?Feat:=20"=EC=9E=AC=EB=A3=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=9E=AC=EB=A3=8C=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. IngredientResponse에 불필요한 생성자 제거 2. tbl_ingredient_category와 tbl_ingredient_storage에 카테고리와 보관방법 SQL로 몇 가지 INSERT 3. 재료명 조회 시 category_pk, storage_pk가 아닌 카테고리명과 보관방법명이 나오도록 수정 4. 재료 수정 기능 구현 5. 재료 삭제 기능 구현 -> ingredientManagementPk 를 url에 추가 입력하면 삭제 가능 --- .../ingredient/IngredientController.java | 14 ++++ .../request/IngredientCreateRequest.java | 4 +- .../request/IngredientUpdateRequest.java | 16 ++++ .../response/IngredientResponse.java | 13 +--- .../IngredientManagementRepository.java | 1 + .../service/ingredient/IngredientService.java | 3 + .../ingredient/IngredientServiceImpl.java | 73 ++++++++++++++----- 7 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 0e821ac..ac328ce 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -1,6 +1,7 @@ package moja.refrigerator.controller.ingredient; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; @@ -29,4 +30,17 @@ public void createIngredient(@RequestBody IngredientCreateRequest request) { public List getIngredient() { return ingredientService.getIngredient(); } + + // 재료 정보 수정 + @PutMapping + public void updateIngredient(@RequestBody IngredientUpdateRequest request) { + ingredientService.updateIngredient(request); + } + + // 재료 삭제 + @DeleteMapping + public void deleteIngredient(@RequestParam long ingredientManagementPK) { + ingredientService.deleteIngredient(ingredientManagementPK); + } + } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java index ac63e4b..eacc7e4 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java @@ -9,6 +9,6 @@ public class IngredientCreateRequest { private String registrationDate; private int seasonDate; -// private int ingredientCategoryPk; -// private int ingredientStoragePk; + private int ingredientCategoryPk; + private int ingredientStoragePk; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java new file mode 100644 index 0000000..f1abb73 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java @@ -0,0 +1,16 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class IngredientUpdateRequest { + + private long ingredientManagementPk; + private String ingredientName; + private String expirationDate; + private String registrationDate; + private int seasonDate; + private int ingredientCategoryPk; + private int ingredientStoragePk; + +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java index a98038f..5ce316c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java @@ -9,16 +9,11 @@ public class IngredientResponse { private String expirationDate; private String registrationDate; private int seasonDate; + // 조회 시에는 pk 말고 이름으로 조회 되도록 + private String ingredientCategory; + private String ingredientStorage; - // ModelMapper를 위한 기본 생성자 생성 + // ModelMapper 를 위한 기본 생성자 생성 public IngredientResponse() {} - // 생성자 - public IngredientResponse(long ingredientManagementPk, String ingredientName, String expirationDate, String registrationDate, int seasonDate) { - this.ingredientManagementPk = ingredientManagementPk; - this.ingredientName = ingredientName; - this.expirationDate = expirationDate; - this.registrationDate = registrationDate; - this.seasonDate = seasonDate; - } } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java index 7a6e9f3..4278b26 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientManagementRepository.java @@ -6,5 +6,6 @@ @Repository public interface IngredientManagementRepository extends JpaRepository { + } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 45d10c0..8dcff37 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -1,6 +1,7 @@ package moja.refrigerator.service.ingredient; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; +import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import java.util.List; @@ -8,4 +9,6 @@ public interface IngredientService { void createIngredient(IngredientCreateRequest request); // 재료 등록 메서드 List getIngredient(); // 재료 조회 메서드 + void updateIngredient(IngredientUpdateRequest request); + void deleteIngredient(long ingredientManagementPK); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 92465ca..0002328 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -1,13 +1,14 @@ package moja.refrigerator.service.ingredient; -//import moja.refrigerator.aggregate.ingredient.IngredientCategory; +import moja.refrigerator.aggregate.ingredient.IngredientCategory; import moja.refrigerator.aggregate.ingredient.IngredientManagement; -//import moja.refrigerator.aggregate.ingredient.IngredientStorage; +import moja.refrigerator.aggregate.ingredient.IngredientStorage; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; -//import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; +import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; +import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; -//import moja.refrigerator.repository.ingredient.IngredientStorageRepository; +import moja.refrigerator.repository.ingredient.IngredientStorageRepository; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -20,18 +21,18 @@ public class IngredientServiceImpl implements IngredientService{ private IngredientManagementRepository ingredientManagementRepository; -// private IngredientStorageRepository ingredientStorageRepository; -// private IngredientCategoryRepository ingredientCategoryRepository; + private IngredientStorageRepository ingredientStorageRepository; + private IngredientCategoryRepository ingredientCategoryRepository; private ModelMapper mapper; @Autowired public IngredientServiceImpl(IngredientManagementRepository ingredientManagementRepository, -// IngredientStorageRepository ingredientStorageRepository, -// IngredientCategoryRepository ingredientCategoryRepository, + IngredientStorageRepository ingredientStorageRepository, + IngredientCategoryRepository ingredientCategoryRepository, ModelMapper mapper) { this.ingredientManagementRepository = ingredientManagementRepository; -// this.ingredientStorageRepository = ingredientStorageRepository; -// this.ingredientCategoryRepository = ingredientCategoryRepository; + this.ingredientStorageRepository = ingredientStorageRepository; + this.ingredientCategoryRepository = ingredientCategoryRepository; this.mapper = mapper; } @@ -40,14 +41,14 @@ public IngredientServiceImpl(IngredientManagementRepository ingredientManagement public void createIngredient(IngredientCreateRequest request) { IngredientManagement ingredient = mapper.map(request, IngredientManagement.class); -// IngredientCategory category = ingredientCategoryRepository.findById(request.getIngredientCategoryPk()) -// .orElseThrow(() -> new IllegalArgumentException("카테고리를 찾을 수 없습니다.")); -// -// IngredientStorage storage = ingredientStorageRepository.findById(request.getIngredientStoragePk()) -// .orElseThrow(() -> new IllegalArgumentException("저장소를 찾을 수 없습니다.")); -// -// ingredient.setIngredientCategory(category); -// ingredient.setIngredientStorage(storage); + IngredientCategory category = ingredientCategoryRepository.findById(request.getIngredientCategoryPk()) + .orElseThrow(() -> new IllegalArgumentException("카테고리를 찾을 수 없습니다.")); + + IngredientStorage storage = ingredientStorageRepository.findById(request.getIngredientStoragePk()) + .orElseThrow(() -> new IllegalArgumentException("해당 보관 방법을 찾을 수 없습니다.")); + + ingredient.setIngredientCategory(category); + ingredient.setIngredientStorage(storage); // 재료를 JpaRepository의 save() 메소드로 DB에 저장 ! ingredientManagementRepository.save(ingredient); @@ -63,4 +64,40 @@ public List getIngredient() { .collect(Collectors.toList()); } + @Override + @Transactional + public void updateIngredient(IngredientUpdateRequest request) { + // 1. 수정할 재료 조회 + IngredientManagement ingredient = ingredientManagementRepository + .findById(request.getIngredientManagementPk()) + .orElseThrow(() -> new IllegalArgumentException("수정할 재료를 찾을 수 없습니다.")); + + // 2. 새로운 카테고리와 저장소 조회 + IngredientCategory newCategory = ingredientCategoryRepository.findById(request.getIngredientCategoryPk()) + .orElseThrow(() -> new IllegalArgumentException("카테고리를 찾을 수 없습니다.")); + + IngredientStorage newStorage = ingredientStorageRepository.findById(request.getIngredientStoragePk()) + .orElseThrow(() -> new IllegalArgumentException("해당 보관 방법을 찾을 수 없습니다.")); + + // 3. 기본 필드들 업데이트 + ingredient.setIngredientName(request.getIngredientName()); + ingredient.setExpirationDate(request.getExpirationDate()); + ingredient.setRegistrationDate(request.getRegistrationDate()); + ingredient.setSeasonDate(request.getSeasonDate()); + + // 4. 연관관계 설정 + ingredient.setIngredientCategory(newCategory); + ingredient.setIngredientStorage(newStorage); + } + + @Override + @Transactional + public void deleteIngredient(long ingredientManagementPK) { + IngredientManagement ingredient = ingredientManagementRepository + .findById(ingredientManagementPK) + .orElseThrow(() -> new IllegalArgumentException("삭제할 재료를 찾을 수 없습니다.")); + + ingredientManagementRepository.delete(ingredient); + } + } From b470539a6c33f1d4be96677b32a8acc2df78d7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Thu, 12 Dec 2024 21:41:24 +0900 Subject: [PATCH 16/46] =?UTF-8?q?Fix:=20SecurityConfig=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 회원가입 경로에 맞게 URL 접근 권한 수정 Related to: #13 --- .../main/java/moja/refrigerator/config/SecurityConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 0449c5e..cca1627 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -35,8 +35,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((auth) -> auth .requestMatchers("/auth/**").permitAll() // 이 경로들은 모두 접근 가능 - .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 - .anyRequest().authenticated()); // 나머지는 인증된 사용자만 + .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 + .anyRequest().authenticated()); // 나머지는 인증된 사용자만 // 세션 관리 설정 http From 557c6db72798e7af178e38cc2c24957fff70ca6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Fri, 13 Dec 2024 12:52:26 +0900 Subject: [PATCH 17/46] =?UTF-8?q?fix:=20Security=20url=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코드 순서 수정, 403 forbidden 에러 해결 Resolves: #12 --- refrigerator/.idea/dataSources.xml | 14 +++++ refrigerator/.idea/modules.xml | 8 +++ .../.idea/modules/refrigerator.main.iml | 8 +++ .../refrigerator/config/SecurityConfig.java | 2 +- .../ingredient/IngredientController.java | 32 ++++------ .../service/ingredient/IngredientService.java | 6 +- .../ingredient/IngredientServiceImpl.java | 63 +++++++++---------- 7 files changed, 78 insertions(+), 55 deletions(-) create mode 100644 refrigerator/.idea/modules.xml create mode 100644 refrigerator/.idea/modules/refrigerator.main.iml diff --git a/refrigerator/.idea/dataSources.xml b/refrigerator/.idea/dataSources.xml index acfaa41..f038683 100644 --- a/refrigerator/.idea/dataSources.xml +++ b/refrigerator/.idea/dataSources.xml @@ -13,5 +13,19 @@ $ProjectFileDir$ + + mysql.8 + true + true + $PROJECT_DIR$/src/main/resources/application.yml + com.mysql.cj.jdbc.Driver + jdbc:mysql://localhost:3306/refrigerator + + + + + + $ProjectFileDir$ + \ No newline at end of file diff --git a/refrigerator/.idea/modules.xml b/refrigerator/.idea/modules.xml new file mode 100644 index 0000000..bdc72c3 --- /dev/null +++ b/refrigerator/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml new file mode 100644 index 0000000..afc1871 --- /dev/null +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 17e66a6..2970b11 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -34,7 +34,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // URL 별 접근 권한 설정 http .authorizeHttpRequests((auth) -> auth - .requestMatchers("/login", "/", "/join").permitAll() // 이 경로들은 모두 접근 가능 + .requestMatchers("/login", "/", "/join", "/ingredient").permitAll() // 이 경로들은 모두 접근 가능 .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 3d9577f..19bf7af 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -3,18 +3,12 @@ import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; -import moja.refrigerator.service.ingredient.IngredientService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -36,16 +30,6 @@ public void createIngredient(@RequestBody IngredientCreateRequest request) { ingredientService.createIngredient(request); } - - @PostMapping("/bookmark/regist") - public ResponseEntity createIngredientBookmark( - @RequestBody RequestRegistIngredientBookmark requestBookmark - ) { - ResponseRegistIngredientBookmark responseBookmark = - ingredientService.createIngredientBookmark(requestBookmark); - - return ResponseEntity.status(HttpStatus.CREATED).body(responseBookmark); - // 재료 조회 @GetMapping public List getIngredient() { @@ -61,8 +45,18 @@ public void updateIngredient(@RequestBody IngredientUpdateRequest request) { // 재료 삭제 @DeleteMapping - public void deleteIngredient(@RequestParam long ingredientManagementPK) { - ingredientService.deleteIngredient(ingredientManagementPK); + public void deleteIngredient(@RequestParam long ingredientManagementPk) { + ingredientService.deleteIngredient(ingredientManagementPk); + } + + @PostMapping("/bookmark/regist") + public ResponseEntity createIngredientBookmark( + @RequestBody RequestRegistIngredientBookmark requestBookmark + ) { + ResponseRegistIngredientBookmark responseBookmark = + ingredientService.createIngredientBookmark(requestBookmark); + + return ResponseEntity.status(HttpStatus.CREATED).body(responseBookmark); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index ee40007..61ba28f 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -2,11 +2,11 @@ import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; + import java.util.List; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; public interface IngredientService { // void createIngredient(IngredientCreateRequest request); @@ -17,5 +17,5 @@ public interface IngredientService { List getIngredient(); // 재료 조회 메서드 void updateIngredient(IngredientUpdateRequest request); - void deleteIngredient(long ingredientManagementPK); + void deleteIngredient(long ingredientManagementPk); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index eb1391a..5b7b9e1 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -1,22 +1,21 @@ package moja.refrigerator.service.ingredient; +import jakarta.persistence.EntityNotFoundException; +import moja.refrigerator.aggregate.ingredient.IngredientBookmark; import moja.refrigerator.aggregate.ingredient.IngredientCategory; import moja.refrigerator.aggregate.ingredient.IngredientManagement; import moja.refrigerator.aggregate.ingredient.IngredientStorage; +import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; -import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; -import moja.refrigerator.repository.ingredient.IngredientManagementRepository; -import moja.refrigerator.repository.ingredient.IngredientStorageRepository; -import jakarta.persistence.EntityNotFoundException; -import moja.refrigerator.aggregate.ingredient.IngredientBookmark; -import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; import moja.refrigerator.repository.ingredient.IngredientBookmarkRepository; +import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; +import moja.refrigerator.repository.ingredient.IngredientManagementRepository; +import moja.refrigerator.repository.ingredient.IngredientStorageRepository; import moja.refrigerator.repository.user.UserRepository; - import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.springframework.beans.factory.annotation.Autowired; @@ -69,28 +68,6 @@ public void createIngredient(IngredientCreateRequest request) { ingredientManagementRepository.save(ingredient); } - @Override - - public ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIngredientBookmark requestBookmark) { - User user = userRepository.findById(requestBookmark.getUserPk()) - .orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다.")); - - IngredientManagement ingredientManagement = ingredientManagementRepository - .findById(requestBookmark.getIngredientPk()) - .orElseThrow(() -> new EntityNotFoundException("재료를 찾을 수 없습니다.")); - - IngredientBookmark ingredientBookmark = new IngredientBookmark(); - - ingredientBookmark.setUser(user); - ingredientBookmark.setIngredientManagement(ingredientManagement); - - ingredientBookmarkRepository.save(ingredientBookmark); - - mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); - - return mapper.map(ingredientBookmark, ResponseRegistIngredientBookmark.class); - } - @Transactional(readOnly = true) public List getIngredient() { List ingredients = ingredientManagementRepository.findAll(); @@ -128,12 +105,34 @@ public void updateIngredient(IngredientUpdateRequest request) { @Override @Transactional - public void deleteIngredient(long ingredientManagementPK) { + public void deleteIngredient(long ingredientManagementPk) { IngredientManagement ingredient = ingredientManagementRepository - .findById(ingredientManagementPK) + .findById(ingredientManagementPk) .orElseThrow(() -> new IllegalArgumentException("삭제할 재료를 찾을 수 없습니다.")); ingredientManagementRepository.delete(ingredient); } + @Override + public ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIngredientBookmark requestBookmark) { + User user = userRepository.findById(requestBookmark.getUserPk()) + .orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다.")); + + IngredientManagement ingredientManagement = ingredientManagementRepository + .findById(requestBookmark.getIngredientPk()) + .orElseThrow(() -> new EntityNotFoundException("재료를 찾을 수 없습니다.")); + + IngredientBookmark ingredientBookmark = new IngredientBookmark(); + + ingredientBookmark.setUser(user); + ingredientBookmark.setIngredientManagement(ingredientManagement); + + ingredientBookmarkRepository.save(ingredientBookmark); + + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + + return mapper.map(ingredientBookmark, ResponseRegistIngredientBookmark.class); + } + + } From d488662181c79502f975ea40c74b781fe032099f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Fri, 13 Dec 2024 14:07:40 +0900 Subject: [PATCH 18/46] =?UTF-8?q?Chore:=20=EB=AA=A8=EB=93=A0=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=91=EA=B7=BC=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 개발 중 접근 편의성을 위해 모든 경로에 대한 인증 요구 제거함 Related to: #11 --- refrigerator/.idea/modules.xml | 8 ++++++++ refrigerator/.idea/modules/refrigerator.main.iml | 8 ++++++++ .../java/moja/refrigerator/config/SecurityConfig.java | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 refrigerator/.idea/modules.xml create mode 100644 refrigerator/.idea/modules/refrigerator.main.iml diff --git a/refrigerator/.idea/modules.xml b/refrigerator/.idea/modules.xml new file mode 100644 index 0000000..bdc72c3 --- /dev/null +++ b/refrigerator/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml new file mode 100644 index 0000000..afc1871 --- /dev/null +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index cca1627..948026c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -34,7 +34,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // URL 별 접근 권한 설정 http .authorizeHttpRequests((auth) -> auth - .requestMatchers("/auth/**").permitAll() // 이 경로들은 모두 접근 가능 + .requestMatchers("/**").permitAll() // 이 경로들은 모두 접근 가능 .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 From 88a31cc47e522eaab3495b65e7033aafaaa94b1e Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Fri, 13 Dec 2024 17:48:48 +0900 Subject: [PATCH 19/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=20=EC=A6=90?= =?UTF-8?q?=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. UserPk를 받아 사용자가 즐겨찾기 한 재료 조회 Related to: #3 --- .../controller/ingredient/IngredientController.java | 12 ++++++++++++ .../request/RequestIngredientBookmarkLists.java | 8 ++++++++ .../ResponseUsersIngredientBookmarkLists.java | 9 +++++++++ .../ingredient/IngredientBookmarkRepository.java | 3 +++ .../service/ingredient/IngredientService.java | 4 ++++ .../service/ingredient/IngredientServiceImpl.java | 13 +++++++++++++ 6 files changed, 49 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestIngredientBookmarkLists.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 19bf7af..a02373b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -2,9 +2,11 @@ import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; +import moja.refrigerator.dto.ingredient.request.RequestIngredientBookmarkLists; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.ResponseUsersIngredientBookmarkLists; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -59,4 +61,14 @@ public ResponseEntity createIngredientBookmark return ResponseEntity.status(HttpStatus.CREATED).body(responseBookmark); } + @GetMapping("/bookmark") + public ResponseEntity> getUsersIngredientBookmarkList( + @RequestBody RequestIngredientBookmarkLists requestBookmarkLists + ) { + List responseBookmarkLists = + ingredientService.getUsersIngredientBookmarkLists(requestBookmarkLists); + + return ResponseEntity.status(HttpStatus.OK).body(responseBookmarkLists); + } + } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestIngredientBookmarkLists.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestIngredientBookmarkLists.java new file mode 100644 index 0000000..7bafd4a --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestIngredientBookmarkLists.java @@ -0,0 +1,8 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class RequestIngredientBookmarkLists { + private long userPk; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java new file mode 100644 index 0000000..868338c --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java @@ -0,0 +1,9 @@ +package moja.refrigerator.dto.ingredient.response; + +import lombok.Data; +import moja.refrigerator.aggregate.ingredient.IngredientManagement; + +@Data +public class ResponseUsersIngredientBookmarkLists { + private IngredientManagement ingredientManagement; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java index 90c2e54..987536f 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientBookmarkRepository.java @@ -3,5 +3,8 @@ import moja.refrigerator.aggregate.ingredient.IngredientBookmark; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface IngredientBookmarkRepository extends JpaRepository { + List findAllByUser_UserPk(long userPk); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 61ba28f..0d54763 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -2,9 +2,11 @@ import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; +import moja.refrigerator.dto.ingredient.request.RequestIngredientBookmarkLists; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.ResponseUsersIngredientBookmarkLists; import java.util.List; @@ -18,4 +20,6 @@ public interface IngredientService { List getIngredient(); // 재료 조회 메서드 void updateIngredient(IngredientUpdateRequest request); void deleteIngredient(long ingredientManagementPk); + + List getUsersIngredientBookmarkLists(RequestIngredientBookmarkLists requestBookmarkLists); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 5b7b9e1..ebef862 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -8,9 +8,11 @@ import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; +import moja.refrigerator.dto.ingredient.request.RequestIngredientBookmarkLists; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; +import moja.refrigerator.dto.ingredient.response.ResponseUsersIngredientBookmarkLists; import moja.refrigerator.repository.ingredient.IngredientBookmarkRepository; import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; @@ -134,5 +136,16 @@ public ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIn return mapper.map(ingredientBookmark, ResponseRegistIngredientBookmark.class); } + @Override + public List getUsersIngredientBookmarkLists( + RequestIngredientBookmarkLists requestBookmarkLists) { + List ingredientBookmarkLists = ingredientBookmarkRepository + .findAllByUser_UserPk(requestBookmarkLists.getUserPk()); + + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + return ingredientBookmarkLists.stream().map(ingredientBookmark -> mapper + .map(ingredientBookmark, ResponseUsersIngredientBookmarkLists.class)) + .collect(Collectors.toList()); + } } From 4e8e430e924f5296d46f7d0d780b98242947a4c8 Mon Sep 17 00:00:00 2001 From: mincheol Date: Fri, 13 Dec 2024 18:02:29 +0900 Subject: [PATCH 20/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=ED=95=9C?= =?UTF-8?q?=20=EC=9D=BC=20:=201.=20recipe=EC=97=90=20recipe=20=EC=A0=81?= =?UTF-8?q?=EC=9D=84=20=EB=9E=80=20=EC=83=9D=EC=84=B1.=202.=20Recipe=20fil?= =?UTF-8?q?e=20=EC=B6=94=EA=B0=80=EC=A4=91=20=EB=AC=B8=EC=A0=9C=EC=A0=90?= =?UTF-8?q?=20:=20(=EA=B8=B0=EC=A1=B4)=201.=20RecipeCreateTime=EC=9D=B4=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=EB=90=98=EB=8A=94=EB=8D=B0=20format=EC=9D=84?= =?UTF-8?q?=20=EC=95=88=EB=90=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 해야할 일 : 1. 마무리 --- .../.idea/modules/refrigerator.main.iml | 15 +++- .../refrigerator/aggregate/recipe/Recipe.java | 11 ++- .../aggregate/recipe/RecipeSource.java | 16 +++- .../refrigerator/aggregate/user/User.java | 2 + .../controller/recipe/RecipeController.java | 8 +- .../recipe/request/RecipeCreateRequest.java | 6 +- ...toy.java => RecipeCategoryRepository.java} | 2 +- .../recipe/RecipeSourceTypeRepository.java | 7 ++ .../repository/user/UserRepository.java | 6 +- .../service/recipe/RecipeService.java | 3 +- .../service/recipe/RecipeServiceImpl.java | 73 ++++++++++++++----- 11 files changed, 112 insertions(+), 37 deletions(-) rename refrigerator/src/main/java/moja/refrigerator/repository/recipe/{RecipeCategoryRepositoy.java => RecipeCategoryRepository.java} (78%) create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index afc1871..e3d9945 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,8 +1,15 @@ - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index fdac2ea..172b3b3 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -1,6 +1,7 @@ package moja.refrigerator.aggregate.recipe; import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.annotation.Nullable; import jakarta.persistence.*; import lombok.Data; import moja.refrigerator.aggregate.user.User; @@ -8,6 +9,8 @@ import org.hibernate.annotations.UpdateTimestamp; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Data @Entity @@ -25,6 +28,8 @@ public class Recipe { @Column(name = "recipe_cooking_time") private int recipeCookingTime; + @Column(name = "recipe_content",columnDefinition = "TEXT") // 길이 제한을 해제하기 위해 text로 설정 + private String recipeContent; @CreationTimestamp @Column(name = "recipe_create_time") @@ -46,11 +51,11 @@ public class Recipe { @ManyToOne private User user; - @JoinColumn(name = "recipe_source") - @ManyToOne - private RecipeSource recipeSource; + @OneToMany (mappedBy = "recipe")// 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 + private List recipeSource = new ArrayList<>(); // 여러 Source가 들어갈 수 있으니까 list로 수정 @JoinColumn(name = "recipe_category") @ManyToOne private RecipeCategory recipeCategory; + } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 8750ffd..f0044f9 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -15,18 +15,28 @@ public class RecipeSource { @Column(name = "recipe_source_pk") private long recipeSourcePk; - @Column(name = "recipe_source_save") + @Column(name = "recipe_source_save") // 저장위치 private String recipeSourceSave; @Column(name = "recipe_source_create_time") private String recipeSourceCreateTime = LocalDateTime.now().toString(); - @Column(name = "recipe_source_file_name") + @Column(name = "recipe_source_file_name",nullable = false) // 저장 파일 명 private String recipeSourceFileName; - @JoinColumn(name = "recipe_source_type") + @JoinColumn(name = "recipe_source_type") // 자료타입 동영상 or 사진 @OneToOne private RecipeSourceType recipeSourceType; + @ManyToOne + @JoinColumn(name = "recipePk") + private Recipe recipe; + + public void setRecipe(Recipe recipe) { + this.recipe = recipe; + if (!recipe.getRecipeSource().contains(this)){ + recipe.getRecipeSource().add(this); + } + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java index 4fcd923..c10c057 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java @@ -33,4 +33,6 @@ public class User { // @Column(name = "leave_date") // private LocalDate leaveDate; + + } diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index 3bb64af..a7b157b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -7,6 +7,7 @@ import moja.refrigerator.service.recipe.RecipeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -21,8 +22,11 @@ public RecipeController(RecipeService recipeService) { } @PostMapping - public void createRecipe(@RequestBody RecipeCreateRequest request){ - recipeService.createRecipe(request); + public void createRecipe( + @RequestPart RecipeCreateRequest request, + @RequestPart (required =false) List files + ){ + recipeService.createRecipe(request,files); } @GetMapping diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java index cf56252..6f81952 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java @@ -11,9 +11,9 @@ public class RecipeCreateRequest { private int recipeCookingTime; private int recipeDifficulty; - private String recipeSource; - private String recipeCategory; - private String userPk; + private long recipeSource; + private long recipeCategory; + private long userPk; // private long recipePk; // 자동 추가 // private String recipeCreateTime; //자동 추가 diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepository.java similarity index 78% rename from refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java rename to refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepository.java index 280d996..43b04aa 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepositoy.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeCategoryRepository.java @@ -7,6 +7,6 @@ import java.util.Optional; @Repository -public interface RecipeCategoryRepositoy extends JpaRepository { +public interface RecipeCategoryRepository extends JpaRepository { Optional findByRecipeCategory(String RecipeCategory); } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java new file mode 100644 index 0000000..498b488 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java @@ -0,0 +1,7 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.RecipeSourceType; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecipeSourceTypeRepository extends JpaRepository { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java index 04cb76c..80f3056 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -4,9 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface UserRepository extends JpaRepository { - boolean existsByUserId(String userId); + boolean existsByUserId(String userId); boolean existsByUserEmail(String userEmail); boolean existsByUserNickname(String userNickname); + Optional findByUserPk(long userPk); + } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index 4d6c154..c17368e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -6,11 +6,12 @@ import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeRepository; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import java.util.List; public interface RecipeService { - void createRecipe(RecipeCreateRequest request); + void createRecipe(RecipeCreateRequest request,List files); List getAllRecipes(); void deleteRecipe(long recipePk); void updateRecipe(RecipeUpdateRequest request); diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index b857df7..5e87056 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -2,22 +2,26 @@ import moja.refrigerator.aggregate.recipe.Recipe; -import moja.refrigerator.aggregate.recipe.RecipeCategory; import moja.refrigerator.aggregate.recipe.RecipeSource; +import moja.refrigerator.aggregate.recipe.RecipeSourceType; +import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeResponse; -import moja.refrigerator.repository.recipe.RecipeCategoryRepositoy; +import moja.refrigerator.repository.recipe.RecipeCategoryRepository; import moja.refrigerator.repository.recipe.RecipeRepository; import moja.refrigerator.repository.recipe.RecipeSourceRepository; import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; -import org.modelmapper.PropertyMap; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import java.awt.*; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; @Service @@ -26,39 +30,70 @@ public class RecipeServiceImpl implements RecipeService { private RecipeRepository recipeRepository; private UserRepository userRepository; private RecipeSourceRepository recipeSourceRepository; - private RecipeCategoryRepositoy recipeCategoryRepositoy; + private RecipeCategoryRepository recipeCategoryRepository; private ModelMapper mapper; + @Value("${spring.servlet.multipart.location}") + private String fileDir; + + // 이미지의 확장자를 확인, 이를 이용해 타입을 분류한다. + private boolean isImageFile(String fileName) { + String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); + return List.of("jpg", "jpeg", "png", "gif").contains(extension); + } + // 동영상의 확장자를 확인, 이를 이용해 타입을 분류한다. + private boolean isVideoFile(String fileName) { + String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); + return List.of("mp4", "avi", "mov", "wmv").contains(extension); + } + // 2가지 동시에 다 쓰는 이유는, 둘다 아닐 경우(ex] exe, java 등 잘못된 확장자를 올릴 시 메시지를 주기 위해) + @Autowired public RecipeServiceImpl( RecipeRepository recipeRepository, ModelMapper mapper, RecipeSourceRepository recipeSourceRepository, UserRepository userRepository, - RecipeCategoryRepositoy recipeCategoryRepositoy + RecipeCategoryRepository recipeCategoryRepository ) { this.recipeRepository = recipeRepository; this.mapper = mapper; this.recipeSourceRepository = recipeSourceRepository; this.userRepository = userRepository; - this.recipeCategoryRepositoy = recipeCategoryRepositoy; + this.recipeCategoryRepository = recipeCategoryRepository; } @Override @Transactional - public void createRecipe(RecipeCreateRequest request) { + public void createRecipe(RecipeCreateRequest request, + List files + ) { Recipe recipe = mapper.map(request, Recipe.class); -// //User 조회 -// User user = userRepository.findById(request.getUserId) -// .orElseThrow(IllegalArgumentException::new); -// recipe.setUserPk(user); - -// //RecipeSource 조회 -// RecipeSource recipeSource = recipeSourceRepository.findById(request.getRecipeSource()) -// .orElseThrow(IllegalArgumentException::new); -// recipe.setRecipeSource(recipeSource); + //User 조회 + User user = userRepository.findById(request.getUserPk()) + .orElseThrow(IllegalArgumentException::new); + recipe.setUser(user); + + //RecipeSource 추가부분 + if(files != null && !files.isEmpty()) { + for(MultipartFile file : files){ + // 1. 작성할 내용 정리 + String recipeSourceFileName = file.getOriginalFilename(); + String recipeSourceSave = fileDir+recipeSourceFileName; + + // 2. 작성한 내용 저장 + RecipeSource recipeSource = new RecipeSource(); + recipeSource.setRecipeSourceSave(recipeSourceSave); + recipeSource.setRecipeSourceFileName(recipeSourceFileName); + // 3. 자료 타입 가져오기. + if(isImageFile(recipeSourceFileName)){ + RecipeSourceType recipeSourceType = recipeSourceTypeRepository + } + + } + } //RecipeCategory // RecipeCategory recipeCategory = .findById(request.getRecipeCategory()) @@ -91,9 +126,9 @@ public void updateRecipe(RecipeUpdateRequest request) { if (request.getRecipeName() != null) recipe.setRecipeName(request.getRecipeName()); if (request.getRecipeCookingTime() != 0) recipe.setRecipeCookingTime(request.getRecipeCookingTime()); if (request.getRecipeDifficulty() != 0) recipe.setRecipeDifficulty(request.getRecipeDifficulty()); - if (request.getRecipeSource() != null) recipe.setRecipeSource(recipeSourceRepository.findByRecipeSourceFileName(request.getRecipeSource()) - .orElseThrow(IllegalArgumentException::new)); - if (request.getRecipeCategory() != null) recipe.setRecipeCategory(recipeCategoryRepositoy.findByRecipeCategory(request.getRecipeCategory()) +// if (request.getRecipeSource() != null) recipe.setRecipeSource(recipeSourceRepository.findByRecipeSourceFileName(request.getRecipeSource()) +// .orElseThrow(IllegalArgumentException::new)); + if (request.getRecipeCategory() != null) recipe.setRecipeCategory(recipeCategoryRepository.findByRecipeCategory(request.getRecipeCategory()) .orElseThrow(IllegalArgumentException::new)); recipeRepository.save(recipe); From 0b7bb4164c18ff5fba96516a1ea8e609acafa3c9 Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Fri, 13 Dec 2024 18:06:58 +0900 Subject: [PATCH 21/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=20=EC=A6=90?= =?UTF-8?q?=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. ingredientBookmarkPk를 받아 사용자가 즐겨찾기 한 재료 삭제 Resolves: #3 --- .../ingredient/IngredientController.java | 21 ++++++++---- .../RequestDeleteIngredientBookmark.java | 8 +++++ .../ResponseDeleteIngredientBookmark.java | 8 +++++ .../service/ingredient/IngredientService.java | 14 ++++---- .../ingredient/IngredientServiceImpl.java | 34 +++++++++++++++---- 5 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestDeleteIngredientBookmark.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseDeleteIngredientBookmark.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index a02373b..a938468 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -1,12 +1,7 @@ package moja.refrigerator.controller.ingredient; -import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; -import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; -import moja.refrigerator.dto.ingredient.request.RequestIngredientBookmarkLists; -import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; -import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; -import moja.refrigerator.dto.ingredient.response.ResponseUsersIngredientBookmarkLists; +import moja.refrigerator.dto.ingredient.request.*; +import moja.refrigerator.dto.ingredient.response.*; import moja.refrigerator.service.ingredient.IngredientService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -71,4 +66,16 @@ public ResponseEntity> getUsersIngred return ResponseEntity.status(HttpStatus.OK).body(responseBookmarkLists); } + @DeleteMapping("/bookmark/delete") + public ResponseEntity deleteIngredientBookmark( + @RequestBody RequestDeleteIngredientBookmark requestDeleteBookmark + ) { + + ResponseDeleteIngredientBookmark responseDeleteIngredientBookmark = + ingredientService.deleteIngredientBookmark(requestDeleteBookmark); + + System.out.println(responseDeleteIngredientBookmark.getMessage()); + return ResponseEntity.status(HttpStatus.OK).body(responseDeleteIngredientBookmark); + } + } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestDeleteIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestDeleteIngredientBookmark.java new file mode 100644 index 0000000..0d7732d --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestDeleteIngredientBookmark.java @@ -0,0 +1,8 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class RequestDeleteIngredientBookmark { + private long ingredientBookmarkPk; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseDeleteIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseDeleteIngredientBookmark.java new file mode 100644 index 0000000..6feed8e --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseDeleteIngredientBookmark.java @@ -0,0 +1,8 @@ +package moja.refrigerator.dto.ingredient.response; + +import lombok.Data; + +@Data +public class ResponseDeleteIngredientBookmark { + String message; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 0d54763..a69f1e3 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -1,12 +1,7 @@ package moja.refrigerator.service.ingredient; -import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; -import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; -import moja.refrigerator.dto.ingredient.request.RequestIngredientBookmarkLists; -import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; -import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; -import moja.refrigerator.dto.ingredient.response.ResponseUsersIngredientBookmarkLists; +import moja.refrigerator.dto.ingredient.request.*; +import moja.refrigerator.dto.ingredient.response.*; import java.util.List; @@ -21,5 +16,8 @@ public interface IngredientService { void updateIngredient(IngredientUpdateRequest request); void deleteIngredient(long ingredientManagementPk); - List getUsersIngredientBookmarkLists(RequestIngredientBookmarkLists requestBookmarkLists); + List getUsersIngredientBookmarkLists( + RequestIngredientBookmarkLists requestBookmarkLists); + + ResponseDeleteIngredientBookmark deleteIngredientBookmark(RequestDeleteIngredientBookmark requestDeleteBookmark); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index ebef862..ea05b5e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -6,13 +6,8 @@ import moja.refrigerator.aggregate.ingredient.IngredientManagement; import moja.refrigerator.aggregate.ingredient.IngredientStorage; import moja.refrigerator.aggregate.user.User; -import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; -import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; -import moja.refrigerator.dto.ingredient.request.RequestIngredientBookmarkLists; -import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; -import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; -import moja.refrigerator.dto.ingredient.response.ResponseUsersIngredientBookmarkLists; +import moja.refrigerator.dto.ingredient.request.*; +import moja.refrigerator.dto.ingredient.response.*; import moja.refrigerator.repository.ingredient.IngredientBookmarkRepository; import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; import moja.refrigerator.repository.ingredient.IngredientManagementRepository; @@ -25,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Service @@ -148,4 +144,28 @@ public List getUsersIngredientBookmarkList .map(ingredientBookmark, ResponseUsersIngredientBookmarkLists.class)) .collect(Collectors.toList()); } + + @Override + public ResponseDeleteIngredientBookmark deleteIngredientBookmark( + RequestDeleteIngredientBookmark requestDeleteBookmark) { + IngredientBookmark ingredientBookmark = ingredientBookmarkRepository + .findById(requestDeleteBookmark.getIngredientBookmarkPk()) + .orElseThrow(() -> new EntityNotFoundException("즐겨찾기를 찾을 수 없습니다.")); + + ResponseDeleteIngredientBookmark response = new ResponseDeleteIngredientBookmark(); + + try { + ingredientBookmarkRepository.deleteById(requestDeleteBookmark.getIngredientBookmarkPk()); + String message = ingredientBookmark.getIngredientManagement() + .getIngredientName() + " 재료의 즐겨찾기를 삭제했습니다"; + response.setMessage(message); + return response; + } catch (Exception e) { + String message = + ingredientBookmark.getIngredientManagement() + .getIngredientName() + " 재료의 즐겨찾기를 삭제 실패했습니다"; + response.setMessage(message); + return response; + } + } } From 4d2a42a3e67abfa1cbe44064976014d93ca45fd5 Mon Sep 17 00:00:00 2001 From: mincheol Date: Fri, 13 Dec 2024 23:17:12 +0900 Subject: [PATCH 22/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=ED=95=9C?= =?UTF-8?q?=20=EC=9D=BC:=201.=20category=20=EB=B0=8F=20userid=EB=A5=BC=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=ED=8C=90=EC=97=90=20=EC=B6=94=EA=B0=80=202.?= =?UTF-8?q?=20recipe=20=EB=B0=8F=20category,=20type=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=203.=20=EC=9D=91=EB=8B=B5=20=EB=B3=80=EA=B2=BD=204.=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EB=84=A3=EC=9D=84=20=EC=88=98=20=EC=9E=87?= =?UTF-8?q?=EB=8A=94=20Controller=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 해야할 일 : 1. 사진 넣기(성공해야함.) --- .idea/vcs.xml | 6 ---- .../refrigerator/aggregate/recipe/Recipe.java | 11 ++++-- .../aggregate/recipe/RecipeSource.java | 6 ++-- .../controller/recipe/RecipeController.java | 8 +++-- .../recipe/request/RecipeCreateRequest.java | 6 ++-- .../dto/recipe/response/RecipeResponse.java | 10 ++++-- .../service/recipe/RecipeService.java | 4 ++- .../service/recipe/RecipeServiceImpl.java | 36 +++++++++++-------- 8 files changed, 53 insertions(+), 34 deletions(-) delete mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index 172b3b3..a8f376e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -1,6 +1,7 @@ package moja.refrigerator.aggregate.recipe; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.annotation.Nullable; import jakarta.persistence.*; import lombok.Data; @@ -51,9 +52,15 @@ public class Recipe { @ManyToOne private User user; - @OneToMany (mappedBy = "recipe")// 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 - private List recipeSource = new ArrayList<>(); // 여러 Source가 들어갈 수 있으니까 list로 수정 + @OneToMany (mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true)// 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 + private List recipeSource = new ArrayList<>() ; // 여러 Source가 들어갈 수 있으니까 list로 수정 + public void addRecipeSource(RecipeSource recipeSource) { + this.recipeSource.add(recipeSource); + if(recipeSource.getRecipe() != this) { + recipeSource.setRecipe(this); + } + } @JoinColumn(name = "recipe_category") @ManyToOne private RecipeCategory recipeCategory; diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index f0044f9..88097a7 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -1,6 +1,8 @@ package moja.refrigerator.aggregate.recipe; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.persistence.*; import lombok.Data; @@ -29,12 +31,12 @@ public class RecipeSource { private RecipeSourceType recipeSourceType; @ManyToOne - @JoinColumn(name = "recipePk") + @JoinColumn(name = "recipe_pk") private Recipe recipe; public void setRecipe(Recipe recipe) { this.recipe = recipe; - if (!recipe.getRecipeSource().contains(this)){ + if(!recipe.getRecipeSource().contains(this)){ recipe.getRecipeSource().add(this); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index a7b157b..fd6708e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -23,10 +23,12 @@ public RecipeController(RecipeService recipeService) { @PostMapping public void createRecipe( - @RequestPart RecipeCreateRequest request, - @RequestPart (required =false) List files + @RequestPart RecipeCreateRequest request + , @RequestPart (required =false) List files ){ - recipeService.createRecipe(request,files); + recipeService.createRecipe(request + , files + ); } @GetMapping diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java index 6f81952..ef8640d 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeCreateRequest.java @@ -10,9 +10,9 @@ public class RecipeCreateRequest { private String recipeName; private int recipeCookingTime; private int recipeDifficulty; - - private long recipeSource; - private long recipeCategory; + private String recipeContent; +// private long recipeSource; + private int recipeCategoryPk; private long userPk; // private long recipePk; // 자동 추가 diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java index 73d7888..301e610 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java @@ -1,6 +1,9 @@ package moja.refrigerator.dto.recipe.response; import lombok.Data; +import moja.refrigerator.aggregate.recipe.RecipeCategory; +import moja.refrigerator.aggregate.recipe.RecipeSource; +import moja.refrigerator.aggregate.user.User; import java.time.LocalDateTime; @@ -12,12 +15,13 @@ public class RecipeResponse { private int recipeCookingTime; private int recipeDifficulty; private long recipeViews; + private String recipeContent; private LocalDateTime recipeCreateTime;; private LocalDateTime recipeUpdateTime; - private String recipeSource; - private String userPk; - private String recipeCategory; + private RecipeSource recipeSource; + private User user; + private RecipeCategory recipeCategory; } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index c17368e..b1e87db 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -11,7 +11,9 @@ import java.util.List; public interface RecipeService { - void createRecipe(RecipeCreateRequest request,List files); + void createRecipe(RecipeCreateRequest request + ,List files + ); List getAllRecipes(); void deleteRecipe(long recipePk); void updateRecipe(RecipeUpdateRequest request); diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index 5e87056..a110662 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -2,6 +2,7 @@ import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.aggregate.recipe.RecipeCategory; import moja.refrigerator.aggregate.recipe.RecipeSource; import moja.refrigerator.aggregate.recipe.RecipeSourceType; import moja.refrigerator.aggregate.user.User; @@ -11,11 +12,13 @@ import moja.refrigerator.repository.recipe.RecipeCategoryRepository; import moja.refrigerator.repository.recipe.RecipeRepository; import moja.refrigerator.repository.recipe.RecipeSourceRepository; +import moja.refrigerator.repository.recipe.RecipeSourceTypeRepository; import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -32,9 +35,10 @@ public class RecipeServiceImpl implements RecipeService { private RecipeSourceRepository recipeSourceRepository; private RecipeCategoryRepository recipeCategoryRepository; private ModelMapper mapper; + private RecipeSourceTypeRepository recipeSourceTypeRepository; @Value("${spring.servlet.multipart.location}") - private String fileDir; + public String fileDir; // 이미지의 확장자를 확인, 이를 이용해 타입을 분류한다. private boolean isImageFile(String fileName) { @@ -54,24 +58,29 @@ public RecipeServiceImpl( ModelMapper mapper, RecipeSourceRepository recipeSourceRepository, UserRepository userRepository, - RecipeCategoryRepository recipeCategoryRepository + RecipeCategoryRepository recipeCategoryRepository, + RecipeSourceTypeRepository recipeSourceTypeRepository ) { this.recipeRepository = recipeRepository; this.mapper = mapper; this.recipeSourceRepository = recipeSourceRepository; this.userRepository = userRepository; this.recipeCategoryRepository = recipeCategoryRepository; + this.recipeSourceTypeRepository=recipeSourceTypeRepository; } @Override - @Transactional - public void createRecipe(RecipeCreateRequest request, - List files + @Transactional(propagation = Propagation.REQUIRED) + public void createRecipe(RecipeCreateRequest request + ,List files ) { + Recipe recipe = new Recipe(); + recipe.setRecipeName(request.getRecipeName()); + recipe.setRecipeContent(request.getRecipeContent()); + recipe.setRecipeDifficulty(request.getRecipeDifficulty()); + recipe.setRecipeCookingTime(request.getRecipeCookingTime()); - Recipe recipe = mapper.map(request, Recipe.class); - - //User 조회 +// User 조회 User user = userRepository.findById(request.getUserPk()) .orElseThrow(IllegalArgumentException::new); recipe.setUser(user); @@ -89,17 +98,16 @@ public void createRecipe(RecipeCreateRequest request, recipeSource.setRecipeSourceFileName(recipeSourceFileName); // 3. 자료 타입 가져오기. if(isImageFile(recipeSourceFileName)){ - RecipeSourceType recipeSourceType = recipeSourceTypeRepository + RecipeSourceType recipeSourceType = recipeSourceTypeRepository.getReferenceById((long)1); } } } - //RecipeCategory -// RecipeCategory recipeCategory = .findById(request.getRecipeCategory()) -// .orElseThrow(IllegalArgumentException::new); -// recipe.setRecipeCategory(recipeCategory); - +// RecipeCategory + RecipeCategory recipeCategory = recipeCategoryRepository.findById(request.getRecipeCategoryPk()) + .orElseThrow(IllegalArgumentException::new); + recipe.setRecipeCategory(recipeCategory); recipeRepository.save(recipe); } From 3343d4dcb809a8e20b544d85fe8b589ad7cc5f09 Mon Sep 17 00:00:00 2001 From: mincheol Date: Fri, 13 Dec 2024 23:54:57 +0900 Subject: [PATCH 23/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=20=EC=A4=91=20=EC=9D=BC=201.=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?=EB=84=A3=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moja/refrigerator/aggregate/recipe/Recipe.java | 10 +++------- .../aggregate/recipe/RecipeSource.java | 10 ---------- .../recipe/RecipeSourceTypeRepository.java | 4 +++- .../service/recipe/RecipeServiceImpl.java | 14 ++++++++++++-- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index a8f376e..ebaa2fc 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -52,15 +52,11 @@ public class Recipe { @ManyToOne private User user; - @OneToMany (mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true)// 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 + @OneToMany // 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 + @JoinColumn (name = "recipe_pk") private List recipeSource = new ArrayList<>() ; // 여러 Source가 들어갈 수 있으니까 list로 수정 - public void addRecipeSource(RecipeSource recipeSource) { - this.recipeSource.add(recipeSource); - if(recipeSource.getRecipe() != this) { - recipeSource.setRecipe(this); - } - } + @JoinColumn(name = "recipe_category") @ManyToOne private RecipeCategory recipeCategory; diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 88097a7..45fba42 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -30,15 +30,5 @@ public class RecipeSource { @OneToOne private RecipeSourceType recipeSourceType; - @ManyToOne - @JoinColumn(name = "recipe_pk") - private Recipe recipe; - - public void setRecipe(Recipe recipe) { - this.recipe = recipe; - if(!recipe.getRecipeSource().contains(this)){ - recipe.getRecipeSource().add(this); - } - } } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java index 498b488..4948bec 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeSourceTypeRepository.java @@ -3,5 +3,7 @@ import moja.refrigerator.aggregate.recipe.RecipeSourceType; import org.springframework.data.jpa.repository.JpaRepository; -public interface RecipeSourceTypeRepository extends JpaRepository { +import java.util.Optional; + +public interface RecipeSourceTypeRepository extends JpaRepository { } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index a110662..cbcde42 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -96,11 +96,21 @@ public void createRecipe(RecipeCreateRequest request RecipeSource recipeSource = new RecipeSource(); recipeSource.setRecipeSourceSave(recipeSourceSave); recipeSource.setRecipeSourceFileName(recipeSourceFileName); + // 3. 자료 타입 가져오기. + + RecipeSourceType recipeSourceType; if(isImageFile(recipeSourceFileName)){ - RecipeSourceType recipeSourceType = recipeSourceTypeRepository.getReferenceById((long)1); + recipeSourceType = recipeSourceTypeRepository.findById(1) + .orElseThrow(IllegalArgumentException::new); + }else if (isVideoFile(recipeSourceFileName)){ + recipeSourceType = recipeSourceTypeRepository.findById(2) + .orElseThrow(IllegalArgumentException::new); + }else{ + throw new IllegalArgumentException("Unsupported file type"); } - + recipeSource.setRecipeSourceType(recipeSourceType); + recipeSourceRepository.save(recipeSource); } } From dec8e7a1b6aee63243b9b6bcd18a1740b5e7013f Mon Sep 17 00:00:00 2001 From: mincheol Date: Sat, 14 Dec 2024 00:30:10 +0900 Subject: [PATCH 24/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=20=EC=A4=91=20=EC=9D=BC=201.=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5!!!!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/moja/refrigerator/aggregate/recipe/RecipeSource.java | 2 +- .../moja/refrigerator/aggregate/recipe/RecipeSourceType.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 45fba42..15edc78 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -27,7 +27,7 @@ public class RecipeSource { private String recipeSourceFileName; @JoinColumn(name = "recipe_source_type") // 자료타입 동영상 or 사진 - @OneToOne + @ManyToOne private RecipeSourceType recipeSourceType; } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java index 8ace140..e4a798a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSourceType.java @@ -8,6 +8,7 @@ @Entity @Data public class RecipeSourceType { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "recipe_source_type_pk") From 9cf81a43c5592e272fa69ef212c7d85815799d37 Mon Sep 17 00:00:00 2001 From: LeeGukgeon Date: Sat, 14 Dec 2024 16:48:31 +0900 Subject: [PATCH 25/46] get recipe detail --- .../.idea/modules/refrigerator.main.iml | 3 +++ refrigerator/build.gradle | 1 - .../refrigerator/aggregate/recipe/Recipe.java | 4 +++ .../controller/recipe/RecipeController.java | 4 +++ .../recipe/response/RecipeDetailResponse.java | 25 +++++++++++++++++++ .../service/recipe/RecipeService.java | 2 ++ .../service/recipe/RecipeServiceImpl.java | 12 +++++++-- 7 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeDetailResponse.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index afc1871..9f498db 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -4,5 +4,8 @@ + + + \ No newline at end of file diff --git a/refrigerator/build.gradle b/refrigerator/build.gradle index 0e3a358..383be4b 100644 --- a/refrigerator/build.gradle +++ b/refrigerator/build.gradle @@ -42,7 +42,6 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' testImplementation 'org.springframework.boot:spring-boot-starter-test' } - tasks.named('test') { useJUnitPlatform() } diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index fdac2ea..f76ffbd 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -8,6 +8,7 @@ import org.hibernate.annotations.UpdateTimestamp; import java.time.LocalDateTime; +import java.util.List; @Data @Entity @@ -53,4 +54,7 @@ public class Recipe { @JoinColumn(name = "recipe_category") @ManyToOne private RecipeCategory recipeCategory; + + @OneToMany(mappedBy = "recipe") + private List recipeIngredients; } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index 3bb64af..2ebfdff 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -3,6 +3,7 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; +import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; import org.springframework.beans.factory.annotation.Autowired; @@ -30,6 +31,9 @@ public List getAllRecipes(){ return recipeService.getAllRecipes(); } + @GetMapping("/{id}") + public RecipeDetailResponse getRecipe(@PathVariable long id){ return recipeService.getRecipe(id);} + @DeleteMapping public void deleteRecipe(@RequestParam long recipePk){ recipeService.deleteRecipe(recipePk); diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeDetailResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeDetailResponse.java new file mode 100644 index 0000000..0fcf203 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeDetailResponse.java @@ -0,0 +1,25 @@ +package moja.refrigerator.dto.recipe.response; + +import java.time.LocalDateTime; +import java.util.List; + +import lombok.Data; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; + +@Data +public class RecipeDetailResponse { + private long recipePk; + private String recipeName; + private int recipeCookingTime; + private int recipeDifficulty; + private long recipeViews; + + private LocalDateTime recipeCreateTime;; + private LocalDateTime recipeUpdateTime; + + private String recipeSource; + private String userPk; + private String recipeCategory; + + private List ingredients; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index 4d6c154..3b04e43 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -3,6 +3,7 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; +import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeRepository; import org.springframework.stereotype.Service; @@ -12,6 +13,7 @@ public interface RecipeService { void createRecipe(RecipeCreateRequest request); List getAllRecipes(); + RecipeDetailResponse getRecipe(long id); void deleteRecipe(long recipePk); void updateRecipe(RecipeUpdateRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index b857df7..5c5ceb0 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -4,8 +4,10 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.aggregate.recipe.RecipeCategory; import moja.refrigerator.aggregate.recipe.RecipeSource; +import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; +import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeCategoryRepositoy; import moja.refrigerator.repository.recipe.RecipeRepository; @@ -73,9 +75,15 @@ public List getAllRecipes(){ return recipeRepository.findAll().stream() .map(recipe -> mapper.map(recipe, RecipeResponse.class)) .collect(Collectors.toList()); - }; + } - @Override + public RecipeDetailResponse getRecipe(long id){ + Recipe recipe = recipeRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("recipe not found")); + RecipeDetailResponse response = mapper.map(recipe,RecipeDetailResponse.class); + return response; + } + + @Override public void deleteRecipe(long recipePk) { Recipe recipe = recipeRepository.findByRecipePk(recipePk) .orElseThrow(IllegalArgumentException::new); From 04b19702e2eec708cfc4aa9a2a0e3f7ef896dff8 Mon Sep 17 00:00:00 2001 From: Min Date: Sat, 14 Dec 2024 17:44:09 +0900 Subject: [PATCH 26/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=ED=95=9C?= =?UTF-8?q?=20=EC=9D=BC=201.=20=EC=84=9C=EB=B2=84=20=EC=A0=80=EC=9E=A5(?= =?UTF-8?q?=EC=84=B1=EA=B3=B5).=202.=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EA=B8=B0=20(=EC=84=B1=EA=B3=B5).=20=ED=95=A0=20=EC=9D=BC=201.?= =?UTF-8?q?=20=EC=84=9C=EB=B2=84=20UD(=EC=A0=80=EC=9E=A5=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1214 --- .../.idea/modules/refrigerator.main.iml | 5 ++ refrigerator/build.gradle | 2 +- .../refrigerator/aggregate/recipe/Recipe.java | 4 +- .../aggregate/recipe/RecipeSource.java | 12 ++- .../moja/refrigerator/config/AwsS3Config.java | 35 ++++++++ .../dto/recipe/response/RecipeResponse.java | 3 +- .../service/recipe/RecipeServiceImpl.java | 88 ++++++++++++------- 7 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/config/AwsS3Config.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index e3d9945..ded96ef 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,5 +1,10 @@ + + + + + diff --git a/refrigerator/build.gradle b/refrigerator/build.gradle index 0e3a358..28581c2 100644 --- a/refrigerator/build.gradle +++ b/refrigerator/build.gradle @@ -35,7 +35,7 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.modelmapper:modelmapper:3.1.0' - + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'io.jsonwebtoken:jjwt-api:0.12.3' implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index ebaa2fc..3c16350 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -52,8 +52,8 @@ public class Recipe { @ManyToOne private User user; - @OneToMany // 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 - @JoinColumn (name = "recipe_pk") + @OneToMany(mappedBy = "recipe") // 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 + @JsonManagedReference private List recipeSource = new ArrayList<>() ; // 여러 Source가 들어갈 수 있으니까 list로 수정 diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 15edc78..7fb003c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.persistence.*; import lombok.Data; @@ -21,14 +22,23 @@ public class RecipeSource { private String recipeSourceSave; @Column(name = "recipe_source_create_time") - private String recipeSourceCreateTime = LocalDateTime.now().toString(); + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy.MM.dd", timezone = "Asia/Seoul") + private LocalDateTime recipeSourceCreateTime = LocalDateTime.now(); @Column(name = "recipe_source_file_name",nullable = false) // 저장 파일 명 private String recipeSourceFileName; + @Column(name = "recipe_source_servername") // 서버 저장한 이름 추가. + private String recipeSourceServername; + @JoinColumn(name = "recipe_source_type") // 자료타입 동영상 or 사진 @ManyToOne private RecipeSourceType recipeSourceType; + @ManyToOne + @JoinColumn(name="recipe_pk") + @JsonBackReference + private Recipe recipe; + } diff --git a/refrigerator/src/main/java/moja/refrigerator/config/AwsS3Config.java b/refrigerator/src/main/java/moja/refrigerator/config/AwsS3Config.java new file mode 100644 index 0000000..83707b2 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/config/AwsS3Config.java @@ -0,0 +1,35 @@ +package moja.refrigerator.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AwsS3Config { + + // S3를 등록한 사람이 전달받은 접속하기 위한 key 값 + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + + // S3를 등록한 사람이 전달받은 접속하기 위한 secret key 값 + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + + // S3를 등록한 사람이 S3를 사용할 지역 + @Value("${cloud.aws.region.static}") + private String region; + + // 전달받은 Accesskey 와 SecretKey 로 아마존 서비스 실행 준비 + @Bean + public AmazonS3Client amazonS3Client() { + BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey); + return (AmazonS3Client) AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCreds)) + .build(); + } +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java index 301e610..5686857 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeResponse.java @@ -6,6 +6,7 @@ import moja.refrigerator.aggregate.user.User; import java.time.LocalDateTime; +import java.util.List; @Data public class RecipeResponse { @@ -20,7 +21,7 @@ public class RecipeResponse { private LocalDateTime recipeCreateTime;; private LocalDateTime recipeUpdateTime; - private RecipeSource recipeSource; + private List recipeSource; private User user; private RecipeCategory recipeCategory; diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index cbcde42..72bf37c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -1,6 +1,8 @@ package moja.refrigerator.service.recipe; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.ObjectMetadata; import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.aggregate.recipe.RecipeCategory; import moja.refrigerator.aggregate.recipe.RecipeSource; @@ -23,8 +25,10 @@ import org.springframework.web.multipart.MultipartFile; import java.awt.*; +import java.io.IOException; import java.util.List; import java.util.Objects; +import java.util.UUID; import java.util.stream.Collectors; @Service @@ -36,9 +40,10 @@ public class RecipeServiceImpl implements RecipeService { private RecipeCategoryRepository recipeCategoryRepository; private ModelMapper mapper; private RecipeSourceTypeRepository recipeSourceTypeRepository; + private final AmazonS3Client amazonS3Client; - @Value("${spring.servlet.multipart.location}") - public String fileDir; + @Value("${cloud.aws.s3.bucket}") + private String bucket; // 이미지의 확장자를 확인, 이를 이용해 타입을 분류한다. private boolean isImageFile(String fileName) { @@ -59,7 +64,8 @@ public RecipeServiceImpl( RecipeSourceRepository recipeSourceRepository, UserRepository userRepository, RecipeCategoryRepository recipeCategoryRepository, - RecipeSourceTypeRepository recipeSourceTypeRepository + RecipeSourceTypeRepository recipeSourceTypeRepository, + AmazonS3Client amazonS3Client ) { this.recipeRepository = recipeRepository; this.mapper = mapper; @@ -67,6 +73,7 @@ public RecipeServiceImpl( this.userRepository = userRepository; this.recipeCategoryRepository = recipeCategoryRepository; this.recipeSourceTypeRepository=recipeSourceTypeRepository; + this.amazonS3Client = amazonS3Client; } @Override @@ -74,50 +81,71 @@ public RecipeServiceImpl( public void createRecipe(RecipeCreateRequest request ,List files ) { - Recipe recipe = new Recipe(); + Recipe recipe = new Recipe(); // mapper를 통한인식이 잘 안됨. -> 그냥 일일이 추가. recipe.setRecipeName(request.getRecipeName()); recipe.setRecipeContent(request.getRecipeContent()); recipe.setRecipeDifficulty(request.getRecipeDifficulty()); recipe.setRecipeCookingTime(request.getRecipeCookingTime()); + // User 조회 User user = userRepository.findById(request.getUserPk()) .orElseThrow(IllegalArgumentException::new); recipe.setUser(user); +// RecipeCategory + RecipeCategory recipeCategory = recipeCategoryRepository.findById(request.getRecipeCategoryPk()) + .orElseThrow(IllegalArgumentException::new); + recipe.setRecipeCategory(recipeCategory); //RecipeSource 추가부분 if(files != null && !files.isEmpty()) { for(MultipartFile file : files){ - // 1. 작성할 내용 정리 - String recipeSourceFileName = file.getOriginalFilename(); - String recipeSourceSave = fileDir+recipeSourceFileName; - - // 2. 작성한 내용 저장 - RecipeSource recipeSource = new RecipeSource(); - recipeSource.setRecipeSourceSave(recipeSourceSave); - recipeSource.setRecipeSourceFileName(recipeSourceFileName); - - // 3. 자료 타입 가져오기. - - RecipeSourceType recipeSourceType; - if(isImageFile(recipeSourceFileName)){ - recipeSourceType = recipeSourceTypeRepository.findById(1) - .orElseThrow(IllegalArgumentException::new); - }else if (isVideoFile(recipeSourceFileName)){ - recipeSourceType = recipeSourceTypeRepository.findById(2) - .orElseThrow(IllegalArgumentException::new); - }else{ - throw new IllegalArgumentException("Unsupported file type"); + try{// 1. 작성할 내용 정리 + String recipeSourceFileName = file.getOriginalFilename(); + UUID uuid = UUID.randomUUID(); + String recipeSourceServername = uuid+recipeSourceFileName; + + String recipeSourceSave = "https://"+bucket+"/recipe/"+recipeSourceServername; + + + // 2. 작성한 내용 저장 + RecipeSource recipeSource = new RecipeSource(); + recipeSource.setRecipeSourceServername(recipeSourceServername); + recipeSource.setRecipeSourceSave(recipeSourceSave); + recipeSource.setRecipeSourceFileName(recipeSourceFileName); + + + // 3. 자료 타입 가져오기. + + RecipeSourceType recipeSourceType; + if(isImageFile(recipeSourceFileName)){ + recipeSourceType = recipeSourceTypeRepository.findById(1) + .orElseThrow(IllegalArgumentException::new); + }else if (isVideoFile(recipeSourceFileName)){ + recipeSourceType = recipeSourceTypeRepository.findById(2) + .orElseThrow(IllegalArgumentException::new); + }else{ + throw new IllegalArgumentException("Unsupported file type"); + } + + // 아마존 서버 올리기 + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType(file.getContentType()); + objectMetadata.setContentLength(file.getSize()); + amazonS3Client.putObject(bucket,recipeSourceFileName,file.getInputStream(),objectMetadata); + + // 레시피 db에 저장. + recipeSource.setRecipeSourceType(recipeSourceType); + recipeSource.setRecipe(recipe); + recipeSourceRepository.save(recipeSource); + break; + }catch (IOException e){ + System.out.println(e.getMessage()); } - recipeSource.setRecipeSourceType(recipeSourceType); - recipeSourceRepository.save(recipeSource); + } } -// RecipeCategory - RecipeCategory recipeCategory = recipeCategoryRepository.findById(request.getRecipeCategoryPk()) - .orElseThrow(IllegalArgumentException::new); - recipe.setRecipeCategory(recipeCategory); recipeRepository.save(recipe); } From df0f374765ca9dc8fa40e2a0e7e49a00430ec27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Sat, 14 Dec 2024 20:38:25 +0900 Subject: [PATCH 27/46] =?UTF-8?q?=EC=9E=AC=EB=A3=8C=C3=A3=C2=84fix:CRUD=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ingredient/IngredientManagement.java | 6 -- .../ingredient/IngredientMyRefrigerator.java | 34 +++++++ .../ingredient/IngredientController.java | 16 ++-- .../request/IngredientCreateRequest.java | 6 +- .../request/IngredientUpdateRequest.java | 7 +- .../response/IngredientResponse.java | 8 +- .../IngredientMyRefrigeratorRepository.java | 13 +++ .../service/ingredient/IngredientService.java | 8 +- .../ingredient/IngredientServiceImpl.java | 90 ++++++++----------- .../service/user/UserServiceImpl.java | 2 +- 10 files changed, 106 insertions(+), 84 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientMyRefrigerator.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientMyRefrigeratorRepository.java diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java index 5a9e5bb..dfd453f 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientManagement.java @@ -16,12 +16,6 @@ public class IngredientManagement { @Column(name = "ingredient_name") private String ingredientName; - @Column(name = "expiration_date") - private String expirationDate; - - @Column(name = "registration_date") - private String registrationDate; - @Column(name = "season_date") private int seasonDate; diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientMyRefrigerator.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientMyRefrigerator.java new file mode 100644 index 0000000..c0dc51f --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientMyRefrigerator.java @@ -0,0 +1,34 @@ +package moja.refrigerator.aggregate.ingredient; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Data +@Entity +@Table(name = "tbl_ingredient_my_refrigerator") +public class IngredientMyRefrigerator { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ingredient_my_refrigerator_pk") + private long ingredientMyRefrigeratorPk; + + @ManyToOne + @JoinColumn(name = "user_pk") + private User user; + + @ManyToOne + @JoinColumn(name = "ingredient_management_pk") + private IngredientManagement ingredientManagement; + + @Column(name = "expiration_date") + private String expirationDate; + + @Column(name = "registration_date") + private String registrationDate; + + @Column(name = "ingredient_amount") + private float ingredientAmount; + +} diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 19bf7af..7802d18 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -26,15 +26,17 @@ public IngredientController(IngredientService ingredientService) { // 재료 등록 @PostMapping - public void createIngredient(@RequestBody IngredientCreateRequest request) { - ingredientService.createIngredient(request); + public void createIngredient( + @RequestBody IngredientCreateRequest request, + @RequestParam Long userPk, + @RequestParam Long ingredientManagementPk) { + ingredientService.createIngredient(request, userPk, ingredientManagementPk); } // 재료 조회 @GetMapping - public List getIngredient() { - return ingredientService.getIngredient(); - + public List getIngredient(@RequestParam Long userPk) { + return ingredientService.getIngredient(userPk); } // 재료 정보 수정 @@ -45,8 +47,8 @@ public void updateIngredient(@RequestBody IngredientUpdateRequest request) { // 재료 삭제 @DeleteMapping - public void deleteIngredient(@RequestParam long ingredientManagementPk) { - ingredientService.deleteIngredient(ingredientManagementPk); + public void deleteIngredient(@RequestParam Long ingredientMyRefrigeratorPk) { + ingredientService.deleteIngredient(ingredientMyRefrigeratorPk); } @PostMapping("/bookmark/regist") diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java index eacc7e4..e78f743 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientCreateRequest.java @@ -4,11 +4,9 @@ @Data public class IngredientCreateRequest { - private String ingredientName; + + private float ingredientAmount; private String expirationDate; private String registrationDate; - private int seasonDate; - private int ingredientCategoryPk; - private int ingredientStoragePk; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java index f1abb73..ad2ee5f 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientUpdateRequest.java @@ -5,12 +5,9 @@ @Data public class IngredientUpdateRequest { - private long ingredientManagementPk; - private String ingredientName; + private long ingredientMyRefrigeratorPk; + private float ingredientAmount; private String expirationDate; private String registrationDate; - private int seasonDate; - private int ingredientCategoryPk; - private int ingredientStoragePk; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java index 5ce316c..760db5b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java @@ -4,13 +4,13 @@ @Data public class IngredientResponse { - private long ingredientManagementPk; + + private int number; + private long ingredientMyRefrigeratorPk; private String ingredientName; + private int ingredientAmount; private String expirationDate; - private String registrationDate; private int seasonDate; - // 조회 시에는 pk 말고 이름으로 조회 되도록 - private String ingredientCategory; private String ingredientStorage; // ModelMapper 를 위한 기본 생성자 생성 diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientMyRefrigeratorRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientMyRefrigeratorRepository.java new file mode 100644 index 0000000..19561f3 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/ingredient/IngredientMyRefrigeratorRepository.java @@ -0,0 +1,13 @@ +package moja.refrigerator.repository.ingredient; + +import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface IngredientMyRefrigeratorRepository extends JpaRepository { + // 사용자 PK로 해당 사용자의 냉장고 재료 목록 조회 + List findByUserUserPk(Long userPk); +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 61ba28f..08c701b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -9,13 +9,13 @@ import java.util.List; public interface IngredientService { -// void createIngredient(IngredientCreateRequest request); ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIngredientBookmark requestBookmark); - void createIngredient(IngredientCreateRequest request); // 재료 등록 메서드 + void createIngredient(IngredientCreateRequest request, Long userPk, Long ingredientManagementPk); // 재료 등록 메서드 - List getIngredient(); // 재료 조회 메서드 + List getIngredient(Long userPk); // 재료 조회 메서드 void updateIngredient(IngredientUpdateRequest request); - void deleteIngredient(long ingredientManagementPk); + void deleteIngredient(long ingredientMyRefrigeratorPk); + } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 5b7b9e1..0ab0d9b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -1,20 +1,14 @@ package moja.refrigerator.service.ingredient; import jakarta.persistence.EntityNotFoundException; -import moja.refrigerator.aggregate.ingredient.IngredientBookmark; -import moja.refrigerator.aggregate.ingredient.IngredientCategory; -import moja.refrigerator.aggregate.ingredient.IngredientManagement; -import moja.refrigerator.aggregate.ingredient.IngredientStorage; +import moja.refrigerator.aggregate.ingredient.*; import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.ingredient.request.IngredientCreateRequest; import moja.refrigerator.dto.ingredient.request.IngredientUpdateRequest; import moja.refrigerator.dto.ingredient.request.RequestRegistIngredientBookmark; import moja.refrigerator.dto.ingredient.response.IngredientResponse; import moja.refrigerator.dto.ingredient.response.ResponseRegistIngredientBookmark; -import moja.refrigerator.repository.ingredient.IngredientBookmarkRepository; -import moja.refrigerator.repository.ingredient.IngredientCategoryRepository; -import moja.refrigerator.repository.ingredient.IngredientManagementRepository; -import moja.refrigerator.repository.ingredient.IngredientStorageRepository; +import moja.refrigerator.repository.ingredient.*; import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; @@ -23,94 +17,84 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @Service public class IngredientServiceImpl implements IngredientService{ private IngredientManagementRepository ingredientManagementRepository; - private IngredientStorageRepository ingredientStorageRepository; - private IngredientCategoryRepository ingredientCategoryRepository; private IngredientBookmarkRepository ingredientBookmarkRepository; + private IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository; private UserRepository userRepository; private ModelMapper mapper; @Autowired public IngredientServiceImpl(IngredientManagementRepository ingredientManagementRepository, - IngredientStorageRepository ingredientStorageRepository, - IngredientCategoryRepository ingredientCategoryRepository, IngredientBookmarkRepository ingredientBookmarkRepository, + IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository, UserRepository userRepository, ModelMapper mapper) { this.ingredientManagementRepository = ingredientManagementRepository; - this.ingredientStorageRepository = ingredientStorageRepository; - this.ingredientCategoryRepository = ingredientCategoryRepository; this.ingredientBookmarkRepository = ingredientBookmarkRepository; + this.ingredientMyRefrigeratorRepository = ingredientMyRefrigeratorRepository; this.userRepository = userRepository; this.mapper = mapper; } @Override @Transactional - public void createIngredient(IngredientCreateRequest request) { - IngredientManagement ingredient = mapper.map(request, IngredientManagement.class); + public void createIngredient(IngredientCreateRequest request, Long userPk, Long ingredientManagementPk) { + IngredientMyRefrigerator myRefrigerator = mapper.map(request, IngredientMyRefrigerator.class); - IngredientCategory category = ingredientCategoryRepository.findById(request.getIngredientCategoryPk()) - .orElseThrow(() -> new IllegalArgumentException("카테고리를 찾을 수 없습니다.")); + User user = userRepository.findById(userPk) + .orElseThrow(() -> new IllegalArgumentException("회원을 찾을 수 없습니다.")); - IngredientStorage storage = ingredientStorageRepository.findById(request.getIngredientStoragePk()) - .orElseThrow(() -> new IllegalArgumentException("해당 보관 방법을 찾을 수 없습니다.")); + IngredientManagement ingredientManagement = ingredientManagementRepository.findById(ingredientManagementPk) + .orElseThrow(() -> new IllegalArgumentException("재료를 찾을 수 없습니다.")); - ingredient.setIngredientCategory(category); - ingredient.setIngredientStorage(storage); + myRefrigerator.setUser(user); + myRefrigerator.setIngredientManagement(ingredientManagement); // 재료를 JpaRepository의 save() 메소드로 DB에 저장 ! - ingredientManagementRepository.save(ingredient); + ingredientMyRefrigeratorRepository.save(myRefrigerator); } @Transactional(readOnly = true) - public List getIngredient() { - List ingredients = ingredientManagementRepository.findAll(); + public List getIngredient(Long userPk) { + List ingredients = ingredientMyRefrigeratorRepository.findByUserUserPk(userPk); + + AtomicInteger counter = new AtomicInteger(1); return ingredients.stream() - .map(ingredient -> mapper.map(ingredient, IngredientResponse.class)) + .map(ingredient -> { + IngredientResponse response = mapper.map(ingredient, IngredientResponse.class); + response.setNumber(counter.getAndIncrement()); + response.setIngredientName(ingredient.getIngredientManagement().getIngredientName()); + response.setSeasonDate(ingredient.getIngredientManagement().getSeasonDate()); + response.setIngredientStorage(ingredient.getIngredientManagement().getIngredientStorage().getIngredientStorage()); + return response; + }) .collect(Collectors.toList()); } @Override @Transactional public void updateIngredient(IngredientUpdateRequest request) { - // 1. 수정할 재료 조회 - IngredientManagement ingredient = ingredientManagementRepository - .findById(request.getIngredientManagementPk()) - .orElseThrow(() -> new IllegalArgumentException("수정할 재료를 찾을 수 없습니다.")); - - // 2. 새로운 카테고리와 저장소 조회 - IngredientCategory newCategory = ingredientCategoryRepository.findById(request.getIngredientCategoryPk()) - .orElseThrow(() -> new IllegalArgumentException("카테고리를 찾을 수 없습니다.")); - - IngredientStorage newStorage = ingredientStorageRepository.findById(request.getIngredientStoragePk()) - .orElseThrow(() -> new IllegalArgumentException("해당 보관 방법을 찾을 수 없습니다.")); - - // 3. 기본 필드들 업데이트 - ingredient.setIngredientName(request.getIngredientName()); - ingredient.setExpirationDate(request.getExpirationDate()); - ingredient.setRegistrationDate(request.getRegistrationDate()); - ingredient.setSeasonDate(request.getSeasonDate()); - - // 4. 연관관계 설정 - ingredient.setIngredientCategory(newCategory); - ingredient.setIngredientStorage(newStorage); + IngredientMyRefrigerator ingredient = ingredientMyRefrigeratorRepository + .findById(request.getIngredientMyRefrigeratorPk()) + .orElseThrow(() -> new EntityNotFoundException("수정할 재료를 찾을 수 없습니다.")); + + mapper.map(request, ingredient); } @Override @Transactional - public void deleteIngredient(long ingredientManagementPk) { - IngredientManagement ingredient = ingredientManagementRepository - .findById(ingredientManagementPk) - .orElseThrow(() -> new IllegalArgumentException("삭제할 재료를 찾을 수 없습니다.")); - - ingredientManagementRepository.delete(ingredient); + public void deleteIngredient(long ingredientMyRefrigeratorPk) { + if (!ingredientMyRefrigeratorRepository.existsById(ingredientMyRefrigeratorPk)) { + throw new EntityNotFoundException("삭제할 재료를 찾을 수 없습니다."); + } + ingredientMyRefrigeratorRepository.deleteById(ingredientMyRefrigeratorPk); } @Override diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 4413f85..0fbf06a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -13,4 +13,4 @@ public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder pass this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; } -} +} \ No newline at end of file From 25ee5a46ea46fbe775cd62927b2f5fdb60880495 Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Sat, 14 Dec 2024 23:27:32 +0900 Subject: [PATCH 28/46] =?UTF-8?q?Feat:=20=EC=9E=AC=EB=A3=8C=20=EC=A6=90?= =?UTF-8?q?=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 사용자 냉장고 생성에 따른 로직 수정 Resolves: #14 --- .../aggregate/ingredient/IngredientBookmark.java | 4 ++-- .../request/RequestRegistIngredientBookmark.java | 2 +- .../response/ResponseRegistIngredientBookmark.java | 3 ++- .../ResponseUsersIngredientBookmarkLists.java | 3 ++- .../service/ingredient/IngredientServiceImpl.java | 14 +++++++------- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java index 5140c88..b609706 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/ingredient/IngredientBookmark.java @@ -19,6 +19,6 @@ public class IngredientBookmark { private User user; @ManyToOne - @JoinColumn(name = "ingredient_management_pk") - private IngredientManagement ingredientManagement; + @JoinColumn(name = "ingredient_my_refrigerator_pk") + private IngredientMyRefrigerator ingredientMyRefrigerator; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java index 33c0ccf..61cb5ac 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestRegistIngredientBookmark.java @@ -5,5 +5,5 @@ @Data public class RequestRegistIngredientBookmark { private long userPk; - private long ingredientPk; + private long ingredientMyRefrigeratorPk; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java index 41c5dab..439616d 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseRegistIngredientBookmark.java @@ -3,11 +3,12 @@ import lombok.Data; import moja.refrigerator.aggregate.ingredient.IngredientBookmark; import moja.refrigerator.aggregate.ingredient.IngredientManagement; +import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator; import moja.refrigerator.aggregate.user.User; @Data public class ResponseRegistIngredientBookmark { private long ingredientBookmarkPk; private User user; - private IngredientManagement ingredientManagement; + private IngredientMyRefrigerator ingredientMyRefrigerator; } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java index 868338c..c279d91 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseUsersIngredientBookmarkLists.java @@ -2,8 +2,9 @@ import lombok.Data; import moja.refrigerator.aggregate.ingredient.IngredientManagement; +import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator; @Data public class ResponseUsersIngredientBookmarkLists { - private IngredientManagement ingredientManagement; + private IngredientMyRefrigerator ingredientMyRefrigerator; } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 13cf998..3b4c2aa 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -102,14 +102,14 @@ public ResponseRegistIngredientBookmark createIngredientBookmark(RequestRegistIn User user = userRepository.findById(requestBookmark.getUserPk()) .orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다.")); - IngredientManagement ingredientManagement = ingredientManagementRepository - .findById(requestBookmark.getIngredientPk()) + IngredientMyRefrigerator ingredientManagement = ingredientMyRefrigeratorRepository + .findById(requestBookmark.getIngredientMyRefrigeratorPk()) .orElseThrow(() -> new EntityNotFoundException("재료를 찾을 수 없습니다.")); IngredientBookmark ingredientBookmark = new IngredientBookmark(); ingredientBookmark.setUser(user); - ingredientBookmark.setIngredientManagement(ingredientManagement); + ingredientBookmark.setIngredientMyRefrigerator(ingredientManagement); ingredientBookmarkRepository.save(ingredientBookmark); @@ -142,14 +142,14 @@ public ResponseDeleteIngredientBookmark deleteIngredientBookmark( try { ingredientBookmarkRepository.deleteById(requestDeleteBookmark.getIngredientBookmarkPk()); - String message = ingredientBookmark.getIngredientManagement() - .getIngredientName() + " 재료의 즐겨찾기를 삭제했습니다"; + String message = ingredientBookmark.getIngredientMyRefrigerator() + .getIngredientManagement().getIngredientName() + " 재료의 즐겨찾기를 삭제했습니다"; response.setMessage(message); return response; } catch (Exception e) { String message = - ingredientBookmark.getIngredientManagement() - .getIngredientName() + " 재료의 즐겨찾기를 삭제 실패했습니다"; + ingredientBookmark.getIngredientMyRefrigerator() + .getIngredientManagement().getIngredientName() + " 재료의 즐겨찾기를 삭제 실패했습니다"; response.setMessage(message); return response; } From 6a64edc9adfb3f43a34a98f935e6f2d97d9e1d48 Mon Sep 17 00:00:00 2001 From: mincheol Date: Sun, 15 Dec 2024 00:27:27 +0900 Subject: [PATCH 29/46] =?UTF-8?q?[=EA=B9=80=EB=AF=BC=EC=B2=A0]=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=ED=95=9C=20=EC=9D=BC=201.=20Recipe=20CRUD=20=EC=A0=84?= =?UTF-8?q?=EB=B6=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1215 --- .../refrigerator/aggregate/recipe/Recipe.java | 2 +- .../aggregate/recipe/RecipeSource.java | 2 +- .../controller/recipe/RecipeController.java | 7 +- .../service/recipe/RecipeService.java | 5 +- .../service/recipe/RecipeServiceImpl.java | 88 +++++++++++++++++-- 5 files changed, 91 insertions(+), 13 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java index 3c16350..a4694b0 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/Recipe.java @@ -52,7 +52,7 @@ public class Recipe { @ManyToOne private User user; - @OneToMany(mappedBy = "recipe") // 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 + @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true,fetch = FetchType.LAZY) // 1개의 레시피에 여러 이미지가 들어갈 수 있으니까 수정 @JsonManagedReference private List recipeSource = new ArrayList<>() ; // 여러 Source가 들어갈 수 있으니까 list로 수정 diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java index 7fb003c..c69c19b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeSource.java @@ -35,7 +35,7 @@ public class RecipeSource { @ManyToOne private RecipeSourceType recipeSourceType; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="recipe_pk") @JsonBackReference private Recipe recipe; diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index fd6708e..fe871c3 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -42,7 +42,10 @@ public void deleteRecipe(@RequestParam long recipePk){ } @PutMapping - public void updateRecipe(@RequestBody RecipeUpdateRequest request){ - recipeService.updateRecipe(request); + public void updateRecipe( + @RequestPart RecipeUpdateRequest request + ,@RequestPart (required =false) List files + ){ + recipeService.updateRecipe(request,files); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index b1e87db..8ace55e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -16,5 +16,8 @@ void createRecipe(RecipeCreateRequest request ); List getAllRecipes(); void deleteRecipe(long recipePk); - void updateRecipe(RecipeUpdateRequest request); + void updateRecipe( + RecipeUpdateRequest request + ,List files + ); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index 72bf37c..f694662 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -2,6 +2,8 @@ import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.aggregate.recipe.RecipeCategory; @@ -132,7 +134,7 @@ public void createRecipe(RecipeCreateRequest request ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentType(file.getContentType()); objectMetadata.setContentLength(file.getSize()); - amazonS3Client.putObject(bucket,recipeSourceFileName,file.getInputStream(),objectMetadata); + amazonS3Client.putObject(bucket,recipeSourceServername,file.getInputStream(),objectMetadata); // 레시피 db에 저장. recipeSource.setRecipeSourceType(recipeSourceType); @@ -160,24 +162,94 @@ public List getAllRecipes(){ public void deleteRecipe(long recipePk) { Recipe recipe = recipeRepository.findByRecipePk(recipePk) .orElseThrow(IllegalArgumentException::new); + List sources = recipe.getRecipeSource(); + if(sources!=null && !sources.isEmpty()){ + for (RecipeSource recipeSource : sources) { + amazonS3Client.deleteObject( new DeleteObjectRequest(bucket,recipeSource.getRecipeSourceServername())); + } + } recipeRepository.delete(recipe); + } @Override @Transactional - public void updateRecipe(RecipeUpdateRequest request) { + public void updateRecipe(RecipeUpdateRequest request, List files) { Recipe recipe = recipeRepository.findByRecipePk(request.getRecipePk()) - .orElseThrow(IllegalArgumentException::new); + .orElseThrow(() -> new IllegalArgumentException("Recipe not found")); + // 기본 필드 업데이트 if (request.getRecipeName() != null) recipe.setRecipeName(request.getRecipeName()); if (request.getRecipeCookingTime() != 0) recipe.setRecipeCookingTime(request.getRecipeCookingTime()); if (request.getRecipeDifficulty() != 0) recipe.setRecipeDifficulty(request.getRecipeDifficulty()); -// if (request.getRecipeSource() != null) recipe.setRecipeSource(recipeSourceRepository.findByRecipeSourceFileName(request.getRecipeSource()) -// .orElseThrow(IllegalArgumentException::new)); - if (request.getRecipeCategory() != null) recipe.setRecipeCategory(recipeCategoryRepository.findByRecipeCategory(request.getRecipeCategory()) - .orElseThrow(IllegalArgumentException::new)); + if (request.getRecipeCategory() != null) { + recipe.setRecipeCategory(recipeCategoryRepository.findByRecipeCategory(request.getRecipeCategory()) + .orElseThrow(() -> new IllegalArgumentException("Category not found"))); + } - recipeRepository.save(recipe); + // 기존 RecipeSource와 업로드된 파일 비교 + List sources = recipe.getRecipeSource(); + List uploadedFileNames = files.stream() + .map(MultipartFile::getOriginalFilename) + .toList(); + + // 삭제할 RecipeSource + List recipeSourcesToDelete = sources.stream() + .filter(source -> !uploadedFileNames.contains(source.getRecipeSourceFileName())) + .toList(); + for (RecipeSource recipeSource : recipeSourcesToDelete) { + amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, recipeSource.getRecipeSourceServername())); + recipe.getRecipeSource().remove(recipeSource); // 부모 엔티티에서 참조 제거 + recipeSourceRepository.delete(recipeSource ); + } + // 추가할 새 파일 + List existingFileNames = sources.stream() + .map(RecipeSource::getRecipeSourceFileName) + .toList(); + + List filesToAdd = files.stream() + .filter(file -> !existingFileNames.contains(file.getOriginalFilename())) + .toList(); + + for (MultipartFile file : filesToAdd) { + try { + // 새 RecipeSource 생성 + String recipeSourceFileName = UUID.randomUUID() + "_" + file.getOriginalFilename(); + String recipeSourceServername = recipeSourceFileName; + String recipeSourceSave = "https://" + bucket + "/recipe/" + recipeSourceServername; + + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType(file.getContentType()); + objectMetadata.setContentLength(file.getSize()); + amazonS3Client.putObject(bucket, recipeSourceServername, file.getInputStream(), objectMetadata); + + RecipeSource recipeSource = new RecipeSource(); + recipeSource.setRecipeSourceServername(recipeSourceServername); + recipeSource.setRecipeSourceSave(recipeSourceSave); + recipeSource.setRecipeSourceFileName(file.getOriginalFilename()); + + RecipeSourceType recipeSourceType; + if (isImageFile(file.getOriginalFilename())) { + recipeSourceType = recipeSourceTypeRepository.findById(1) + .orElseThrow(() -> new IllegalArgumentException("Image type not found")); + } else if (isVideoFile(file.getOriginalFilename())) { + recipeSourceType = recipeSourceTypeRepository.findById(2) + .orElseThrow(() -> new IllegalArgumentException("Video type not found")); + } else { + throw new IllegalArgumentException("Unsupported file type"); + } + + recipeSource.setRecipeSourceType(recipeSourceType); + recipeSource.setRecipe(recipe); + recipeSourceRepository.save(recipeSource); + } catch (IOException e) { + throw new RuntimeException("Error processing file: " + file.getOriginalFilename(), e); + } + } + + // 최종 저장 + recipeRepository.save(recipe); } + } \ No newline at end of file From d52ee780b746e885e1afecec7d7dbb1560d285ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Sun, 15 Dec 2024 12:45:18 +0900 Subject: [PATCH 30/46] =?UTF-8?q?fix:=20=EC=9C=A0=ED=86=B5=EA=B8=B0?= =?UTF-8?q?=ED=95=9C=20=EB=82=A8=EC=9D=80=20=EC=9D=BC=EC=88=98=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=8F=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refrigerator/.idea/dataSources.xml | 14 ++++++++++++++ .../ingredient/response/IngredientResponse.java | 3 ++- .../service/ingredient/IngredientServiceImpl.java | 14 +++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/refrigerator/.idea/dataSources.xml b/refrigerator/.idea/dataSources.xml index f038683..b572de5 100644 --- a/refrigerator/.idea/dataSources.xml +++ b/refrigerator/.idea/dataSources.xml @@ -27,5 +27,19 @@ $ProjectFileDir$ + + mysql.8 + true + true + $PROJECT_DIR$/src/main/resources/application.yml + com.mysql.cj.jdbc.Driver + jdbc:mysql://localhost:3306/test_refrigerator + + + + + + $ProjectFileDir$ + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java index 760db5b..bda5d0b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/IngredientResponse.java @@ -8,8 +8,9 @@ public class IngredientResponse { private int number; private long ingredientMyRefrigeratorPk; private String ingredientName; - private int ingredientAmount; + private float ingredientAmount; private String expirationDate; + private long remainExpirationDate; private int seasonDate; private String ingredientStorage; diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 3b4c2aa..d3014e9 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -15,6 +15,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.Comparator; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.Optional; @@ -56,7 +59,7 @@ public void createIngredient(IngredientCreateRequest request, Long userPk, Long myRefrigerator.setUser(user); myRefrigerator.setIngredientManagement(ingredientManagement); - // 재료를 JpaRepository의 save() 메소드로 DB에 저장 ! + // 재료를 JpaRepository 의 save() 메소드로 DB에 저장 ! ingredientMyRefrigeratorRepository.save(myRefrigerator); } @@ -64,6 +67,7 @@ public void createIngredient(IngredientCreateRequest request, Long userPk, Long public List getIngredient(Long userPk) { List ingredients = ingredientMyRefrigeratorRepository.findByUserUserPk(userPk); + LocalDate currentDate = LocalDate.now(); AtomicInteger counter = new AtomicInteger(1); return ingredients.stream() @@ -73,8 +77,16 @@ public List getIngredient(Long userPk) { response.setIngredientName(ingredient.getIngredientManagement().getIngredientName()); response.setSeasonDate(ingredient.getIngredientManagement().getSeasonDate()); response.setIngredientStorage(ingredient.getIngredientManagement().getIngredientStorage().getIngredientStorage()); + + // 현재 날짜 기준, 유통기한 남은 일수 계산 + LocalDate expirationDate = LocalDate.parse(ingredient.getExpirationDate()); + long remainExpirationDate = ChronoUnit.DAYS.between(currentDate, expirationDate); + response.setRemainExpirationDate(remainExpirationDate); + return response; }) + // 남은 일수 기준 오름차순 정렬 + .sorted(Comparator.comparingLong(IngredientResponse::getRemainExpirationDate)) .collect(Collectors.toList()); } From 1281ac827e81dd576b0786cec9081be2a676004d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Sun, 15 Dec 2024 12:47:19 +0900 Subject: [PATCH 31/46] =?UTF-8?q?Feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LoginFilter: 클라이언트가 보낸 아이디와 비밀번호 받음 - CustomUserDetailsService: 사용자 정보 조회 - CustomUserDetails: 사용자 정보 포맷 Related to: #20 --- .../.idea/modules/refrigerator.main.iml | 15 ----- .../refrigerator/config/SecurityConfig.java | 20 ++++++ .../dto/user/CustomUserDetails.java | 61 +++++++++++++++++++ .../moja/refrigerator/jwt/LoginFilter.java | 43 +++++++++++++ .../repository/user/UserRepository.java | 4 +- .../user/CustomUserDetailsService.java | 27 ++++++++ .../service/user/UserServiceImpl.java | 1 + 7 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index 397c268..afc1871 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -4,20 +4,5 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 948026c..90cf817 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -1,22 +1,39 @@ package moja.refrigerator.config; +import moja.refrigerator.jwt.LoginFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig { + //bAuthenticationManager가 인자로 받을 AuthenticationConfiguraion 객체 생성자 주입 + private final AuthenticationConfiguration authenticationConfiguration; + + public SecurityConfig(AuthenticationConfiguration authenticationConfiguration) { + this.authenticationConfiguration = authenticationConfiguration; + } + @Bean // 비밀번호 암호화를 위한 인코더 public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } + //AuthenticationManager Bean 등록 + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { + return configuration.getAuthenticationManager(); + } + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // csrf 보안 비활성화 @@ -38,6 +55,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 + http + .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration)), UsernamePasswordAuthenticationFilter.class); + // 세션 관리 설정 http .sessionManagement((session) -> session diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java new file mode 100644 index 0000000..2a9b277 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java @@ -0,0 +1,61 @@ +package moja.refrigerator.dto.user; + +import moja.refrigerator.aggregate.user.User; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; + +public class CustomUserDetails implements UserDetails { + private final User user; + + public CustomUserDetails(User user) { + this.user = user; + } + + @Override + public Collection getAuthorities() { + + Collection collection = new ArrayList<>(); + + collection.add(new GrantedAuthority() { + + @Override + public String getAuthority() { + return user.getRole(); + } + }); + return collection; + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public String getUsername() { + return user.getUsername(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java b/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java new file mode 100644 index 0000000..1f98f69 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java @@ -0,0 +1,43 @@ +package moja.refrigerator.jwt; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +public class LoginFilter extends UsernamePasswordAuthenticationFilter { + private final AuthenticationManager authenticationManager; + + public LoginFilter(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + // 클라이언트 요청에서 username, password 추출 + String username = obtainUsername(request); + String password = obtainPassword(request); + + //스프링 시큐리티에서 username과 password를 검증하기 위해서는 token에 담아야 함 + UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, password, null); + + //token에 담은 검증을 위한 AuthenticationManager로 전달 + return authenticationManager.authenticate(authToken); + } + + //로그인 성공시 실행하는 메소드 (여기서 JWT를 발급하면 됨) + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) { + + } + + //로그인 실패시 실행하는 메소드 + @Override + protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { + + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java index 80f3056..b3b44c0 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -8,9 +8,9 @@ @Repository public interface UserRepository extends JpaRepository { - boolean existsByUserId(String userId); + boolean existsByUserId(String userId); boolean existsByUserEmail(String userEmail); boolean existsByUserNickname(String userNickname); Optional findByUserPk(long userPk); - + Optional findByUserId(String userId); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java new file mode 100644 index 0000000..4c3ef4b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java @@ -0,0 +1,27 @@ +package moja.refrigerator.service.user; + +import moja.refrigerator.aggregate.user.User; +import moja.refrigerator.dto.user.CustomUserDetails; +import moja.refrigerator.repository.user.UserRepository; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + private final UserRepository userRepository; + + public CustomUserDetailsService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + @Transactional + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + User userData = userRepository.findByUserId(username) + .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다: " + username)); + return new CustomUserDetails(userData); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index b52fd64..64388bf 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -39,6 +39,7 @@ public void createUser(UserCreateRequest request) { userRepository.save(user); } + private void checkDuplicateUser(UserCreateRequest request) { List errors = new ArrayList<>(); if (userRepository.existsByUserId(request.getUserId())) { From 4005d7c5fff1cb6e4812cb8532fffdc4a7d23a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=99=8D=EB=B2=94?= Date: Sun, 15 Dec 2024 18:18:07 +0900 Subject: [PATCH 32/46] =?UTF-8?q?fix:=20=EC=9E=AC=EB=A3=8C=20=C3=AC?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=ED=95=A0=20=EC=88=98=EB=9F=89=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ingredient/IngredientController.java | 12 ++++++++-- .../request/IngredientDeleteRequest.java | 11 ++++++++++ .../service/ingredient/IngredientService.java | 2 +- .../ingredient/IngredientServiceImpl.java | 22 +++++++++++++++---- 4 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientDeleteRequest.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index d791df5..7e78ac9 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -1,5 +1,6 @@ package moja.refrigerator.controller.ingredient; +import jakarta.persistence.EntityNotFoundException; import moja.refrigerator.dto.ingredient.request.*; import moja.refrigerator.dto.ingredient.response.*; import moja.refrigerator.service.ingredient.IngredientService; @@ -44,8 +45,15 @@ public void updateIngredient(@RequestBody IngredientUpdateRequest request) { // 재료 삭제 @DeleteMapping - public void deleteIngredient(@RequestParam Long ingredientMyRefrigeratorPk) { - ingredientService.deleteIngredient(ingredientMyRefrigeratorPk); + public ResponseEntity deleteIngredient(@RequestBody IngredientDeleteRequest request) { + try { + ingredientService.deleteIngredient(request); + return ResponseEntity.ok("재료가 성공적으로 삭제되었습니다."); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } catch (EntityNotFoundException e) { + return ResponseEntity.notFound().build(); + } } @PostMapping("/bookmark/regist") diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientDeleteRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientDeleteRequest.java new file mode 100644 index 0000000..063da41 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/IngredientDeleteRequest.java @@ -0,0 +1,11 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class IngredientDeleteRequest { + + private Long ingredientMyRefrigeratorPk; + private float deleteAmount; + +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index 3c237e8..c73c9aa 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -14,7 +14,7 @@ public interface IngredientService { List getIngredient(Long userPk); // 재료 조회 메서드 void updateIngredient(IngredientUpdateRequest request); - void deleteIngredient(long ingredientMyRefrigeratorPk); + void deleteIngredient(IngredientDeleteRequest request); List getUsersIngredientBookmarkLists( RequestIngredientBookmarkLists requestBookmarkLists); diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index d3014e9..3b25f4f 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -102,11 +102,25 @@ public void updateIngredient(IngredientUpdateRequest request) { @Override @Transactional - public void deleteIngredient(long ingredientMyRefrigeratorPk) { - if (!ingredientMyRefrigeratorRepository.existsById(ingredientMyRefrigeratorPk)) { - throw new EntityNotFoundException("삭제할 재료를 찾을 수 없습니다."); + public void deleteIngredient(IngredientDeleteRequest request) { + IngredientMyRefrigerator ingredient = ingredientMyRefrigeratorRepository + .findById(request.getIngredientMyRefrigeratorPk()) + .orElseThrow(() -> new IllegalArgumentException("삭제할 재료를 찾을 수 없습니다.")); + + float currentAmount = ingredient.getIngredientAmount(); + float deleteAmount = request.getDeleteAmount(); + + if (currentAmount < deleteAmount) { + throw new IllegalArgumentException("삭제할 수량이 현재 보유 수량보다 많습니다."); + } + // 삭제할 수량이 딱 맞아 떨어지면 재료를 완전 삭제 + if (currentAmount == deleteAmount) { + ingredientMyRefrigeratorRepository.deleteById(request.getIngredientMyRefrigeratorPk()); + } else { + // 현재 수량 - 삭제할 수량의 계산 결과를 저장 + ingredient.setIngredientAmount(currentAmount - deleteAmount); + ingredientMyRefrigeratorRepository.save(ingredient); } - ingredientMyRefrigeratorRepository.deleteById(ingredientMyRefrigeratorPk); } @Override From 31acc1156ce31528af8dc114e9f2fe237ec4fb2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=ED=9D=AC=EC=A4=80?= Date: Sun, 15 Dec 2024 19:45:36 +0900 Subject: [PATCH 33/46] =?UTF-8?q?Feat=20:=20=EC=9E=AC=EB=A3=8C=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=20=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?1.=20=EC=9C=A0=EC=A0=80=EA=B0=80=20=EB=93=B1=EB=A1=9D=ED=95=9C?= =?UTF-8?q?=20=EC=9E=AC=EB=A3=8C=EB=A5=BC=20=EA=B8=B0=EB=B0=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=202.=20=ED=95=84=EC=88=98?= =?UTF-8?q?=EC=9E=AC=EB=A3=8C=EB=8A=94=20=EB=AA=A8=EB=91=90=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=ED=95=B4=EC=95=BC=ED=95=A8=203.=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EC=9E=AC=EB=A3=8C=20=EC=97=90=EC=84=A0=2066%=20=EC=9D=B4?= =?UTF-8?q?=EC=83=81=EB=A7=8C=20=EC=9E=88=EC=9C=BC=EB=A9=B4=20=EB=90=8C=20?= =?UTF-8?q?4.=20=EC=9C=A0=ED=86=B5=EA=B8=B0=ED=95=9C=EC=9D=B4=20=EA=B0=80?= =?UTF-8?q?=EC=9E=A5=20=EA=B8=B4=EB=B0=95=ED=95=9C=20=EC=9E=AC=EB=A3=8C?= =?UTF-8?q?=EB=AA=85=20,=20=EB=82=A0=EC=A7=9C=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=B4=20Related=20to=20:=20#13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.idea/modules/refrigerator.main.iml | 3 - .../controller/recipe/RecipeController.java | 6 + .../dto/recipe/RecipeMatchResult.java | 15 ++ .../response/RecipeRecommendResponse.java | 14 ++ .../recipe/RecipeIngredientRepository.java | 13 + .../ReplacableIngredientRepository.java | 13 + .../service/recipe/RecipeService.java | 2 + .../service/recipe/RecipeServiceImpl.java | 229 +++++++++++------- 8 files changed, 208 insertions(+), 87 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index 397c268..2d53824 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,9 +1,6 @@ - - - diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index 58807d0..bd4533b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -4,6 +4,7 @@ import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; import org.springframework.beans.factory.annotation.Autowired; @@ -52,4 +53,9 @@ public void updateRecipe( ){ recipeService.updateRecipe(request,files); } + + @GetMapping("/recommend") + public List getRecommendedRecipes(@RequestParam Long userPk) { + return recipeService.getRecommendedRecipes(userPk); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java new file mode 100644 index 0000000..924af00 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java @@ -0,0 +1,15 @@ +package moja.refrigerator.dto.recipe; + +import lombok.AllArgsConstructor; +import lombok.Data; +import moja.refrigerator.aggregate.recipe.Recipe; + +@Data +@AllArgsConstructor +public class RecipeMatchResult { + private Recipe recipe; + private boolean matched; + private double matchRate; + private String urgentIngredient; // 가장 시급한 재료명 + private String urgentExpirationDate; // 해당 재료의 유통기한 +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java new file mode 100644 index 0000000..46bf0c7 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java @@ -0,0 +1,14 @@ +package moja.refrigerator.dto.recipe.response; + +import lombok.Data; + +@Data +public class RecipeRecommendResponse { + private long recipePk; + private String recipeName; + private String recipeContent; + private int recipeCookingTime; + private double matchRate; + private String urgentIngredient; + private String urgentExpirationDate; +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java new file mode 100644 index 0000000..e717f33 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java @@ -0,0 +1,13 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.aggregate.recipe.RecipeIngredient; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface RecipeIngredientRepository extends JpaRepository { + List findByRecipe(Recipe recipe); +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java new file mode 100644 index 0000000..50a497b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java @@ -0,0 +1,13 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.RecipeIngredient; +import moja.refrigerator.aggregate.recipe.ReplacableIngredient; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ReplacableIngredientRepository extends JpaRepository { + List findByRecipeIngredient(RecipeIngredient recipeIngredient); +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index d94057b..7c89c15 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -4,6 +4,7 @@ import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeRepository; import org.springframework.stereotype.Service; @@ -22,4 +23,5 @@ void updateRecipe( RecipeUpdateRequest request ,List files ); + List getRecommendedRecipes(Long userPk); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index 3dddc12..9ec26a2 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -1,24 +1,19 @@ package moja.refrigerator.service.recipe; - import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; -import moja.refrigerator.aggregate.recipe.Recipe; -import moja.refrigerator.aggregate.recipe.RecipeCategory; -import moja.refrigerator.aggregate.recipe.RecipeSource; -import moja.refrigerator.aggregate.recipe.RecipeSourceType; +import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator; +import moja.refrigerator.aggregate.recipe.*; import moja.refrigerator.aggregate.user.User; -import moja.refrigerator.dto.ingredient.response.IngredientResponse; +import moja.refrigerator.dto.recipe.RecipeMatchResult; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; -import moja.refrigerator.repository.recipe.RecipeCategoryRepository; -import moja.refrigerator.repository.recipe.RecipeRepository; -import moja.refrigerator.repository.recipe.RecipeSourceRepository; -import moja.refrigerator.repository.recipe.RecipeSourceTypeRepository; +import moja.refrigerator.repository.ingredient.IngredientMyRefrigeratorRepository; +import moja.refrigerator.repository.recipe.*; import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; @@ -28,125 +23,115 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.awt.*; import java.io.IOException; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; @Service public class RecipeServiceImpl implements RecipeService { - private RecipeRepository recipeRepository; - private UserRepository userRepository; - private RecipeSourceRepository recipeSourceRepository; - private RecipeCategoryRepository recipeCategoryRepository; - private ModelMapper mapper; - private RecipeSourceTypeRepository recipeSourceTypeRepository; + private final RecipeRepository recipeRepository; + private final UserRepository userRepository; + private final RecipeSourceRepository recipeSourceRepository; + private final RecipeCategoryRepository recipeCategoryRepository; + private final ModelMapper mapper; + private final RecipeSourceTypeRepository recipeSourceTypeRepository; private final AmazonS3Client amazonS3Client; + private final IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository; + private final RecipeIngredientRepository recipeIngredientRepository; + private final ReplacableIngredientRepository replacableIngredientRepository; @Value("${cloud.aws.s3.bucket}") private String bucket; - // 이미지의 확장자를 확인, 이를 이용해 타입을 분류한다. - private boolean isImageFile(String fileName) { - String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); - return List.of("jpg", "jpeg", "png", "gif").contains(extension); - } - // 동영상의 확장자를 확인, 이를 이용해 타입을 분류한다. - private boolean isVideoFile(String fileName) { - String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); - return List.of("mp4", "avi", "mov", "wmv").contains(extension); - } - // 2가지 동시에 다 쓰는 이유는, 둘다 아닐 경우(ex] exe, java 등 잘못된 확장자를 올릴 시 메시지를 주기 위해) - @Autowired public RecipeServiceImpl( RecipeRepository recipeRepository, - ModelMapper mapper, - RecipeSourceRepository recipeSourceRepository, UserRepository userRepository, + RecipeSourceRepository recipeSourceRepository, RecipeCategoryRepository recipeCategoryRepository, + ModelMapper mapper, RecipeSourceTypeRepository recipeSourceTypeRepository, - AmazonS3Client amazonS3Client + AmazonS3Client amazonS3Client, + IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository, + RecipeIngredientRepository recipeIngredientRepository, + ReplacableIngredientRepository replacableIngredientRepository ) { this.recipeRepository = recipeRepository; - this.mapper = mapper; - this.recipeSourceRepository = recipeSourceRepository; this.userRepository = userRepository; + this.recipeSourceRepository = recipeSourceRepository; this.recipeCategoryRepository = recipeCategoryRepository; - this.recipeSourceTypeRepository=recipeSourceTypeRepository; + this.mapper = mapper; + this.recipeSourceTypeRepository = recipeSourceTypeRepository; this.amazonS3Client = amazonS3Client; + this.ingredientMyRefrigeratorRepository = ingredientMyRefrigeratorRepository; + this.recipeIngredientRepository = recipeIngredientRepository; + this.replacableIngredientRepository = replacableIngredientRepository; + } + + private boolean isImageFile(String fileName) { + String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); + return List.of("jpg", "jpeg", "png", "gif").contains(extension); + } + + private boolean isVideoFile(String fileName) { + String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); + return List.of("mp4", "avi", "mov", "wmv").contains(extension); } @Override @Transactional(propagation = Propagation.REQUIRED) - public void createRecipe(RecipeCreateRequest request - ,List files - ) { - Recipe recipe = new Recipe(); // mapper를 통한인식이 잘 안됨. -> 그냥 일일이 추가. + public void createRecipe(RecipeCreateRequest request, List files) { + Recipe recipe = new Recipe(); recipe.setRecipeName(request.getRecipeName()); recipe.setRecipeContent(request.getRecipeContent()); recipe.setRecipeDifficulty(request.getRecipeDifficulty()); recipe.setRecipeCookingTime(request.getRecipeCookingTime()); - -// User 조회 User user = userRepository.findById(request.getUserPk()) - .orElseThrow(IllegalArgumentException::new); + .orElseThrow(IllegalArgumentException::new); recipe.setUser(user); -// RecipeCategory RecipeCategory recipeCategory = recipeCategoryRepository.findById(request.getRecipeCategoryPk()) .orElseThrow(IllegalArgumentException::new); recipe.setRecipeCategory(recipeCategory); - //RecipeSource 추가부분 + if(files != null && !files.isEmpty()) { - for(MultipartFile file : files){ - try{// 1. 작성할 내용 정리 + for(MultipartFile file : files) { + try { String recipeSourceFileName = file.getOriginalFilename(); UUID uuid = UUID.randomUUID(); - String recipeSourceServername = uuid+recipeSourceFileName; - - String recipeSourceSave = "https://"+bucket+"/recipe/"+recipeSourceServername; + String recipeSourceServername = uuid + recipeSourceFileName; + String recipeSourceSave = "https://" + bucket + "/recipe/" + recipeSourceServername; - - // 2. 작성한 내용 저장 RecipeSource recipeSource = new RecipeSource(); recipeSource.setRecipeSourceServername(recipeSourceServername); recipeSource.setRecipeSourceSave(recipeSourceSave); recipeSource.setRecipeSourceFileName(recipeSourceFileName); - - // 3. 자료 타입 가져오기. - RecipeSourceType recipeSourceType; - if(isImageFile(recipeSourceFileName)){ + if(isImageFile(recipeSourceFileName)) { recipeSourceType = recipeSourceTypeRepository.findById(1) .orElseThrow(IllegalArgumentException::new); - }else if (isVideoFile(recipeSourceFileName)){ + } else if (isVideoFile(recipeSourceFileName)) { recipeSourceType = recipeSourceTypeRepository.findById(2) .orElseThrow(IllegalArgumentException::new); - }else{ + } else { throw new IllegalArgumentException("Unsupported file type"); } - // 아마존 서버 올리기 ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentType(file.getContentType()); objectMetadata.setContentLength(file.getSize()); - amazonS3Client.putObject(bucket,recipeSourceServername,file.getInputStream(),objectMetadata); + amazonS3Client.putObject(bucket, recipeSourceServername, file.getInputStream(), objectMetadata); - // 레시피 db에 저장. recipeSource.setRecipeSourceType(recipeSourceType); recipeSource.setRecipe(recipe); recipeSourceRepository.save(recipeSource); break; - }catch (IOException e){ + } catch (IOException e) { System.out.println(e.getMessage()); } - } } @@ -154,30 +139,30 @@ public void createRecipe(RecipeCreateRequest request } @Override - public List getAllRecipes(){ + public List getAllRecipes() { return recipeRepository.findAll().stream() .map(recipe -> mapper.map(recipe, RecipeResponse.class)) .collect(Collectors.toList()); } - public RecipeDetailResponse getRecipe(long id){ - Recipe recipe = recipeRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("recipe not found")); - RecipeDetailResponse response = mapper.map(recipe,RecipeDetailResponse.class); - return response; + @Override + public RecipeDetailResponse getRecipe(long id) { + Recipe recipe = recipeRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("recipe not found")); + return mapper.map(recipe, RecipeDetailResponse.class); } - @Override + @Override public void deleteRecipe(long recipePk) { Recipe recipe = recipeRepository.findByRecipePk(recipePk) .orElseThrow(IllegalArgumentException::new); List sources = recipe.getRecipeSource(); - if(sources!=null && !sources.isEmpty()){ + if(sources != null && !sources.isEmpty()) { for (RecipeSource recipeSource : sources) { - amazonS3Client.deleteObject( new DeleteObjectRequest(bucket,recipeSource.getRecipeSourceServername())); + amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, recipeSource.getRecipeSourceServername())); } } recipeRepository.delete(recipe); - } @Override @@ -186,7 +171,6 @@ public void updateRecipe(RecipeUpdateRequest request, List files) Recipe recipe = recipeRepository.findByRecipePk(request.getRecipePk()) .orElseThrow(() -> new IllegalArgumentException("Recipe not found")); - // 기본 필드 업데이트 if (request.getRecipeName() != null) recipe.setRecipeName(request.getRecipeName()); if (request.getRecipeCookingTime() != 0) recipe.setRecipeCookingTime(request.getRecipeCookingTime()); if (request.getRecipeDifficulty() != 0) recipe.setRecipeDifficulty(request.getRecipeDifficulty()); @@ -195,23 +179,21 @@ public void updateRecipe(RecipeUpdateRequest request, List files) .orElseThrow(() -> new IllegalArgumentException("Category not found"))); } - // 기존 RecipeSource와 업로드된 파일 비교 List sources = recipe.getRecipeSource(); List uploadedFileNames = files.stream() .map(MultipartFile::getOriginalFilename) .toList(); - // 삭제할 RecipeSource List recipeSourcesToDelete = sources.stream() .filter(source -> !uploadedFileNames.contains(source.getRecipeSourceFileName())) .toList(); - for (RecipeSource recipeSource : recipeSourcesToDelete) { + + for (RecipeSource recipeSource : recipeSourcesToDelete) { amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, recipeSource.getRecipeSourceServername())); - recipe.getRecipeSource().remove(recipeSource); // 부모 엔티티에서 참조 제거 - recipeSourceRepository.delete(recipeSource ); + recipe.getRecipeSource().remove(recipeSource); + recipeSourceRepository.delete(recipeSource); } - // 추가할 새 파일 List existingFileNames = sources.stream() .map(RecipeSource::getRecipeSourceFileName) .toList(); @@ -222,7 +204,6 @@ public void updateRecipe(RecipeUpdateRequest request, List files) for (MultipartFile file : filesToAdd) { try { - // 새 RecipeSource 생성 String recipeSourceFileName = UUID.randomUUID() + "_" + file.getOriginalFilename(); String recipeSourceServername = recipeSourceFileName; String recipeSourceSave = "https://" + bucket + "/recipe/" + recipeSourceServername; @@ -256,8 +237,88 @@ public void updateRecipe(RecipeUpdateRequest request, List files) } } - // 최종 저장 recipeRepository.save(recipe); } + + @Override + public List getRecommendedRecipes(Long userPk) { + List userIngredients = + ingredientMyRefrigeratorRepository.findByUserUserPk(userPk); + + List allRecipes = recipeRepository.findAll(); + + return allRecipes.stream() + .map(recipe -> checkRecipeMatch(recipe, userIngredients)) + .filter(RecipeMatchResult::isMatched) + .map(result -> { + RecipeRecommendResponse response = mapper.map(result.getRecipe(), RecipeRecommendResponse.class); + response.setMatchRate(result.getMatchRate()); + response.setUrgentIngredient(result.getUrgentIngredient()); // 추가 + response.setUrgentExpirationDate(result.getUrgentExpirationDate()); // 추가 + return response; + }) + .collect(Collectors.toList()); + } + + private RecipeMatchResult checkRecipeMatch(Recipe recipe, List userIngredients) { + List recipeIngredients = recipeIngredientRepository.findByRecipe(recipe); + + if (recipeIngredients.isEmpty()) { + return new RecipeMatchResult(recipe, false, 0, null, null); + } + + // 사용자가 가진 재료의 ID 목록과 유통기한 정보 + Map userIngredientMap = new HashMap<>(); + for (IngredientMyRefrigerator ingredient : userIngredients) { + Long ingredientId = ingredient.getIngredientManagement().getIngredientManagementPk(); + userIngredientMap.put(ingredientId, ingredient); + } + + // 1. 필수 재료 체크 + List necessaryIngredients = recipeIngredients.stream() + .filter(RecipeIngredient::isIngredientIsNecessary) + .toList(); + + + boolean hasAllNecessaryIngredients = true; + for (RecipeIngredient necessary : necessaryIngredients) { + Long necessaryIngredientId = necessary.getIngredientManagement().getIngredientManagementPk(); + if (!userIngredientMap.containsKey(necessaryIngredientId)) { + hasAllNecessaryIngredients = false; + break; + } + } + + // 2. 전체 재료 매칭률 계산 + long matchedCount = recipeIngredients.stream() + .filter(ri -> userIngredientMap.containsKey( + ri.getIngredientManagement().getIngredientManagementPk())) + .count(); + + double matchRate = (double) matchedCount / recipeIngredients.size() * 100; + + // 3. 가장 유통기한이 임박한 재료 찾기 + String urgentIngredient = null; + String urgentExpirationDate = null; + + if (hasAllNecessaryIngredients && matchRate >= 66) { + Optional mostUrgentIngredient = recipeIngredients.stream() + .map(ri -> ri.getIngredientManagement().getIngredientManagementPk()) + .filter(userIngredientMap::containsKey) + .map(userIngredientMap::get) + .min(Comparator.comparing(IngredientMyRefrigerator::getExpirationDate)); + + if (mostUrgentIngredient.isPresent()) { + IngredientMyRefrigerator urgent = mostUrgentIngredient.get(); + urgentIngredient = urgent.getIngredientManagement().getIngredientName(); + urgentExpirationDate = urgent.getExpirationDate(); + } + } + + // 4. 최종 판단: 필수 재료 모두 있고 매칭률 66% 이상 + boolean isMatched = hasAllNecessaryIngredients && matchRate >= 66; + + return new RecipeMatchResult(recipe, isMatched, matchRate, urgentIngredient, urgentExpirationDate); + } } \ No newline at end of file From 2cbfd91a287fc54f4b1fc8b9dc07566011625c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Sun, 15 Dec 2024 21:49:43 +0900 Subject: [PATCH 34/46] =?UTF-8?q?Feat:=20JWT=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20=EC=9D=B8=EC=A6=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - JWTUtil: 토큰 생성 및 검증 기능 구현 - LoginFilter: 로그인 성공 시 JWT 토큰 발급 - JWTFilter: 요청 시 JWT 토큰 검증 및 인증 처리 Resolves: #20 --- .../refrigerator/aggregate/user/User.java | 6 +- .../refrigerator/config/SecurityConfig.java | 20 ++++-- .../controller/user/UserController.java | 9 +-- .../dto/user/CustomUserDetails.java | 14 +--- .../java/moja/refrigerator/jwt/JWTFilter.java | 64 +++++++++++++++++++ .../java/moja/refrigerator/jwt/JWTUtil.java | 46 +++++++++++++ .../moja/refrigerator/jwt/LoginFilter.java | 32 ++++++++-- .../user/CustomUserDetailsService.java | 4 +- .../service/user/UserServiceImpl.java | 1 + 9 files changed, 163 insertions(+), 33 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/jwt/JWTUtil.java diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java index c10c057..03eb039 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/User.java @@ -31,8 +31,6 @@ public class User { @CreationTimestamp private LocalDate joinDate; -// @Column(name = "leave_date") -// private LocalDate leaveDate; - - + @Column(name = "user_role") + private String userRole = "ROLE_USER"; } diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 90cf817..462533f 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -1,5 +1,7 @@ package moja.refrigerator.config; +import moja.refrigerator.jwt.JWTFilter; +import moja.refrigerator.jwt.JWTUtil; import moja.refrigerator.jwt.LoginFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -15,11 +17,14 @@ @Configuration @EnableWebSecurity public class SecurityConfig { - //bAuthenticationManager가 인자로 받을 AuthenticationConfiguraion 객체 생성자 주입 + // AuthenticationManager가 인자로 받을 AuthenticationConfiguraion 객체 생성자 주입 private final AuthenticationConfiguration authenticationConfiguration; + // JWTUtil 주입 + private final JWTUtil jwtUtil; - public SecurityConfig(AuthenticationConfiguration authenticationConfiguration) { + public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil) { this.authenticationConfiguration = authenticationConfiguration; + this.jwtUtil = jwtUtil; } @Bean @@ -28,7 +33,7 @@ public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } - //AuthenticationManager Bean 등록 + // AuthenticationManager Bean 등록 @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception { return configuration.getAuthenticationManager(); @@ -55,14 +60,17 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 - http - .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration)), UsernamePasswordAuthenticationFilter.class); - // 세션 관리 설정 http .sessionManagement((session) -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); // JWT 사용을 위한 세션리스 설정 + // 로그인 필터 추가 + http + .addFilterBefore(new JWTFilter(jwtUtil), LoginFilter.class); + http + .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil), UsernamePasswordAuthenticationFilter.class); + return http.build(); } } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index 324055a..7adacab 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -15,10 +15,11 @@ public UserController(UserService userService) { this.userService = userService; } -// @GetMapping("/") -// public String getMainPage() { -// return "user Controller"; -// } + // 토큰 검증 로직 확인용 + @GetMapping("/") + public String getMainPage() { + return "user Controller"; + } // 회원 가입 처리 @PostMapping("/auth/join") diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java index 2a9b277..2fb2d20 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/CustomUserDetails.java @@ -16,27 +16,19 @@ public CustomUserDetails(User user) { @Override public Collection getAuthorities() { - Collection collection = new ArrayList<>(); - - collection.add(new GrantedAuthority() { - - @Override - public String getAuthority() { - return user.getRole(); - } - }); + collection.add(() -> user.getUserRole()); return collection; } @Override public String getPassword() { - return user.getPassword(); + return user.getUserPw(); } @Override public String getUsername() { - return user.getUsername(); + return user.getUserId(); } @Override diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java b/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java new file mode 100644 index 0000000..e22cfe8 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java @@ -0,0 +1,64 @@ +package moja.refrigerator.jwt; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import moja.refrigerator.aggregate.user.User; +import moja.refrigerator.dto.user.CustomUserDetails; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +public class JWTFilter extends OncePerRequestFilter { + private final JWTUtil jwtUtil; + + public JWTFilter(JWTUtil jwtUtil) { + this.jwtUtil = jwtUtil; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // 헤더에서 토큰 추출 + String authorization = request.getHeader("Authorization"); + + // Authorization 헤더 검증 + if (authorization == null || !authorization.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } + + String token = authorization.split(" ")[1]; + + // 토큰 소멸 시간 검증 + if (jwtUtil.isExpired(token)) { + // 만료된 토큰이면 그냥 통과 + filterChain.doFilter(request, response); + return; + } + + // 토큰에서 정보 추출 + String username = jwtUtil.getUsername(token); + String role = jwtUtil.getRole(token); + + // User를 생성하여 값 set + User user = new User(); + user.setUserId(username); + user.setUserPw("temppassword"); + user.setUserRole(role); + + // UserDetails에 회원 정보 객체 담기 + CustomUserDetails customUserDetails = new CustomUserDetails(user); + + // 스프링 시큐리티 인증 토큰 생성 + Authentication authToken = new UsernamePasswordAuthenticationToken(customUserDetails, null, customUserDetails.getAuthorities()); + + // 세션에 사용자 등록 + SecurityContextHolder.getContext().setAuthentication(authToken); + + filterChain.doFilter(request, response); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/JWTUtil.java b/refrigerator/src/main/java/moja/refrigerator/jwt/JWTUtil.java new file mode 100644 index 0000000..df05cc4 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/JWTUtil.java @@ -0,0 +1,46 @@ +package moja.refrigerator.jwt; + +import io.jsonwebtoken.Jwts; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.Date; + +@Component +public class JWTUtil { + private SecretKey secretKey; + + // application.yml에서 jwt secret key를 가져옴 + public JWTUtil(@Value("${spring.jwt.secret}") String secret) { + this.secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), Jwts.SIG.HS256.key().build().getAlgorithm()); + } + + // 토큰에서 username 추출 + public String getUsername(String token) { + return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("username", String.class); + } + + // 토큰에서 role(권한) 추출 + public String getRole(String token) { + return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("role", String.class); + } + + // 토큰 만료 여부 확인 + public Boolean isExpired(String token) { + return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().getExpiration().before(new Date()); + } + + // 토큰 생성 + public String createJwt(String username, String role, Long expiredMs) { + return Jwts.builder() + .claim("username", username) + .claim("role", role) + .issuedAt(new Date(System.currentTimeMillis())) + .expiration(new Date(System.currentTimeMillis() + expiredMs)) + .signWith(secretKey) + .compact(); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java b/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java index 1f98f69..622aac9 100644 --- a/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java @@ -3,41 +3,61 @@ import jakarta.servlet.FilterChain; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import moja.refrigerator.dto.user.CustomUserDetails; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import java.util.Collection; +import java.util.Iterator; + public class LoginFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; + private final JWTUtil jwtUtil; - public LoginFilter(AuthenticationManager authenticationManager) { + public LoginFilter(AuthenticationManager authenticationManager, JWTUtil jwtUtil) { this.authenticationManager = authenticationManager; + this.jwtUtil = jwtUtil; } + // 로그인 시도 처리 @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { // 클라이언트 요청에서 username, password 추출 String username = obtainUsername(request); String password = obtainPassword(request); - //스프링 시큐리티에서 username과 password를 검증하기 위해서는 token에 담아야 함 + // 이 정보를 토큰으로 만듦 (아직 인증되지 않은 상태) UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, password, null); - //token에 담은 검증을 위한 AuthenticationManager로 전달 + // AuthenticationManager에게 검증 요청 return authenticationManager.authenticate(authToken); } - //로그인 성공시 실행하는 메소드 (여기서 JWT를 발급하면 됨) + // 로그인 성공 처리 - JWT 토큰 발급 @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) { + CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal(); + + String username = customUserDetails.getUsername(); + + Collection authorities = authentication.getAuthorities(); + Iterator iterator = authorities.iterator(); + GrantedAuthority auth = iterator.next(); + String role = auth.getAuthority(); + + String token = jwtUtil.createJwt(username, role, 60*60*10L); + + response.addHeader("Authorization", "Bearer " + token); } - //로그인 실패시 실행하는 메소드 + // 로그인 실패 처리 @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { - + response.setStatus(401); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java index 4c3ef4b..604afac 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/CustomUserDetailsService.java @@ -18,10 +18,10 @@ public CustomUserDetailsService(UserRepository userRepository) { } @Override - @Transactional + @Transactional(readOnly = true) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User userData = userRepository.findByUserId(username) - .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다: " + username)); + .orElseThrow(() -> new UsernameNotFoundException("입력하신 아이디로 가입된 사용자를 찾을 수 없습니다.: " + username)); return new CustomUserDetails(userData); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 64388bf..7cd888b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -35,6 +35,7 @@ public void createUser(UserCreateRequest request) { // 비밀번호 암호화 user.setUserPw(passwordEncoder.encode(request.getUserPw())); + user.setUserRole("ROLE_USER"); userRepository.save(user); } From 0bf19f1cd828c334949eeebb2216fb7d588b5111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=ED=9D=AC=EC=A4=80?= Date: Sun, 15 Dec 2024 23:31:59 +0900 Subject: [PATCH 35/46] =?UTF-8?q?=20Refactor=20:=20=EC=9E=AC=EB=A3=8C?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=B6=94?= =?UTF-8?q?=EC=B2=9C=201.=20=EC=BD=94=EB=93=9C=20=EA=B0=84=EA=B2=B0?= =?UTF-8?q?=ED=99=94=202.=20=EC=9C=A0=ED=86=B5=EA=B8=B0=ED=95=9C=20?= =?UTF-8?q?=EA=B8=B4=EB=B0=95=ED=95=9C=20=EC=9E=AC=EB=A3=8C=EB=AA=85,=20?= =?UTF-8?q?=EB=82=A8=EC=9D=80=20=EC=9D=BC=EC=88=98=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aggregate/recipe/RecipeIngredient.java | 2 + .../dto/recipe/RecipeMatchResult.java | 4 +- .../response/RecipeRecommendResponse.java | 4 +- .../service/recipe/RecipeServiceImpl.java | 87 +++++++++---------- 4 files changed, 47 insertions(+), 50 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java index e530f63..7790098 100644 --- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.Data; import moja.refrigerator.aggregate.ingredient.IngredientManagement; +import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator; @Data @Entity @@ -19,6 +20,7 @@ public class RecipeIngredient { @JoinColumn(name = "ingredient_management") @ManyToOne private IngredientManagement ingredientManagement; +// private IngredientMyRefrigerator ingredientMyRefrigerator ; @JoinColumn(name = "recipe") @ManyToOne diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java index 924af00..210e602 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java @@ -10,6 +10,6 @@ public class RecipeMatchResult { private Recipe recipe; private boolean matched; private double matchRate; - private String urgentIngredient; // 가장 시급한 재료명 - private String urgentExpirationDate; // 해당 재료의 유통기한 + private long remainExpirationDays; + private String urgentIngredientName; } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java index 46bf0c7..dbb6019 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java @@ -9,6 +9,6 @@ public class RecipeRecommendResponse { private String recipeContent; private int recipeCookingTime; private double matchRate; - private String urgentIngredient; - private String urgentExpirationDate; + private long remainExpirationDays; + private String urgentIngredientName; } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index 9ec26a2..9f53d69 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -24,6 +24,8 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @@ -245,7 +247,6 @@ public void updateRecipe(RecipeUpdateRequest request, List files) public List getRecommendedRecipes(Long userPk) { List userIngredients = ingredientMyRefrigeratorRepository.findByUserUserPk(userPk); - List allRecipes = recipeRepository.findAll(); return allRecipes.stream() @@ -254,71 +255,65 @@ public List getRecommendedRecipes(Long userPk) { .map(result -> { RecipeRecommendResponse response = mapper.map(result.getRecipe(), RecipeRecommendResponse.class); response.setMatchRate(result.getMatchRate()); - response.setUrgentIngredient(result.getUrgentIngredient()); // 추가 - response.setUrgentExpirationDate(result.getUrgentExpirationDate()); // 추가 + response.setRemainExpirationDays(result.getRemainExpirationDays()); + response.setUrgentIngredientName(result.getUrgentIngredientName()); return response; }) + .sorted(Comparator.comparingLong(RecipeRecommendResponse::getRemainExpirationDays)) .collect(Collectors.toList()); } private RecipeMatchResult checkRecipeMatch(Recipe recipe, List userIngredients) { List recipeIngredients = recipeIngredientRepository.findByRecipe(recipe); + LocalDate currentDate = LocalDate.now(); if (recipeIngredients.isEmpty()) { - return new RecipeMatchResult(recipe, false, 0, null, null); + return new RecipeMatchResult(recipe, false, 0, 0, null); } - // 사용자가 가진 재료의 ID 목록과 유통기한 정보 - Map userIngredientMap = new HashMap<>(); - for (IngredientMyRefrigerator ingredient : userIngredients) { - Long ingredientId = ingredient.getIngredientManagement().getIngredientManagementPk(); - userIngredientMap.put(ingredientId, ingredient); - } + boolean hasAllNecessaryIngredients = true; + int matchedCount = 0; + long shortestRemainDays = Long.MAX_VALUE; + String urgentIngredientName = null; - // 1. 필수 재료 체크 - List necessaryIngredients = recipeIngredients.stream() - .filter(RecipeIngredient::isIngredientIsNecessary) - .toList(); + for (RecipeIngredient recipeIngredient : recipeIngredients) { + boolean hasIngredient = false; + for (IngredientMyRefrigerator userIngredient : userIngredients) { + if (userIngredient.getIngredientManagement().getIngredientManagementPk() == + recipeIngredient.getIngredientManagement().getIngredientManagementPk()) { - boolean hasAllNecessaryIngredients = true; - for (RecipeIngredient necessary : necessaryIngredients) { - Long necessaryIngredientId = necessary.getIngredientManagement().getIngredientManagementPk(); - if (!userIngredientMap.containsKey(necessaryIngredientId)) { - hasAllNecessaryIngredients = false; - break; + hasIngredient = true; + matchedCount++; + + // 남은 일수 계산 + LocalDate expirationDate = LocalDate.parse(userIngredient.getExpirationDate()); + long remainDays = ChronoUnit.DAYS.between(currentDate, expirationDate); + + // 더 짧은 유통기한 발견시 정보 업데이트 + if (remainDays < shortestRemainDays) { + shortestRemainDays = remainDays; + urgentIngredientName = userIngredient.getIngredientManagement().getIngredientName(); + } + break; + } } - } - // 2. 전체 재료 매칭률 계산 - long matchedCount = recipeIngredients.stream() - .filter(ri -> userIngredientMap.containsKey( - ri.getIngredientManagement().getIngredientManagementPk())) - .count(); - - double matchRate = (double) matchedCount / recipeIngredients.size() * 100; - - // 3. 가장 유통기한이 임박한 재료 찾기 - String urgentIngredient = null; - String urgentExpirationDate = null; - - if (hasAllNecessaryIngredients && matchRate >= 66) { - Optional mostUrgentIngredient = recipeIngredients.stream() - .map(ri -> ri.getIngredientManagement().getIngredientManagementPk()) - .filter(userIngredientMap::containsKey) - .map(userIngredientMap::get) - .min(Comparator.comparing(IngredientMyRefrigerator::getExpirationDate)); - - if (mostUrgentIngredient.isPresent()) { - IngredientMyRefrigerator urgent = mostUrgentIngredient.get(); - urgentIngredient = urgent.getIngredientManagement().getIngredientName(); - urgentExpirationDate = urgent.getExpirationDate(); + if (recipeIngredient.isIngredientIsNecessary() && !hasIngredient) { + hasAllNecessaryIngredients = false; + break; } } - // 4. 최종 판단: 필수 재료 모두 있고 매칭률 66% 이상 + double matchRate = ((double) matchedCount / recipeIngredients.size()) * 100; boolean isMatched = hasAllNecessaryIngredients && matchRate >= 66; - return new RecipeMatchResult(recipe, isMatched, matchRate, urgentIngredient, urgentExpirationDate); + return new RecipeMatchResult( + recipe, + isMatched, + matchRate, + isMatched ? shortestRemainDays : 0, + isMatched ? urgentIngredientName : null + ); } } \ No newline at end of file From f8323179d97e70d35bbb15a8bb59c33dc6e73ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=ED=9D=AC=EC=A4=80?= Date: Mon, 16 Dec 2024 11:41:38 +0900 Subject: [PATCH 36/46] =?UTF-8?q?=20Feat=20:=20=EB=9E=9C=EB=8D=A4=20?= =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=B6=94=EC=B2=9C=201.=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=EB=90=9C=20=EB=A0=88=EC=8B=9C=ED=94=BC=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=ED=9B=84=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=ED=95=98=EA=B2=8C=20=ED=95=9C=EA=B0=9C=20=EC=84=A0?= =?UTF-8?q?=EC=A0=95=202.=20response=20=EB=A1=9C=20=EB=A0=88=EC=8B=9C?= =?UTF-8?q?=ED=94=BC=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- refrigerator/.gitignore | 3 +++ .../controller/recipe/RecipeController.java | 11 +++++++++ .../service/recipe/RecipeService.java | 1 + .../service/recipe/RecipeServiceImpl.java | 23 +++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/refrigerator/.gitignore b/refrigerator/.gitignore index 2b88fe8..68fd73d 100644 --- a/refrigerator/.gitignore +++ b/refrigerator/.gitignore @@ -713,3 +713,6 @@ FodyWeavers.xsd # End of https://www.toptal.com/developers/gitignore/api/macos,windows,git,java,intellij,visualstudio,eclipse,gradle,netbeans /src/main/resources/application.yml + +.idea/ +*.iml diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index bd4533b..d332f82 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -8,6 +8,7 @@ import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -58,4 +59,14 @@ public void updateRecipe( public List getRecommendedRecipes(@RequestParam Long userPk) { return recipeService.getRecommendedRecipes(userPk); } + + @GetMapping("/random") + public ResponseEntity getRandomRecipe() { + try { + RecipeRecommendResponse randomRecipe = recipeService.getRandomRecipe(); + return ResponseEntity.ok(randomRecipe); + } catch (IllegalStateException e) { + return ResponseEntity.notFound().build(); + } + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index 7c89c15..cb89a94 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -24,4 +24,5 @@ void updateRecipe( ,List files ); List getRecommendedRecipes(Long userPk); + RecipeRecommendResponse getRandomRecipe(); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index 9f53d69..e8747bc 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -316,4 +316,27 @@ private RecipeMatchResult checkRecipeMatch(Recipe recipe, List allRecipes = recipeRepository.findAll(); + + // 2. 레시피가 없는 경우 예외 처리 + if (allRecipes.isEmpty()) { + throw new IllegalStateException("등록된 레시피가 없습니다."); + } + + // 3. 랜덤 인덱스 생성 + Random random = new Random(); + int randomIndex = random.nextInt(allRecipes.size()); + + // 4. 랜덤하게 선택된 레시피 + Recipe selectedRecipe = allRecipes.get(randomIndex); + + // 5. Response 객체로 변환 + RecipeRecommendResponse response = mapper.map(selectedRecipe, RecipeRecommendResponse.class); + + return response; + } + } \ No newline at end of file From c85200997613eacd6102b13e8196db0eafcc004f Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Mon, 16 Dec 2024 12:11:02 +0900 Subject: [PATCH 37/46] =?UTF-8?q?Feat:=20=EC=9C=A0=ED=86=B5=EA=B8=B0?= =?UTF-8?q?=ED=95=9C=20=EC=95=8C=EB=9E=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 남은 유통기한 알람 세팅 - 서비스 기능 구현중 - 기능구현 후 로그인에서 비즈니스 로직 이어가도록 수정 Related to: #17 --- .../controller/ingredient/IngredientController.java | 10 ++++++++++ .../ingredient/request/RequestAlertExpirationDate.java | 8 ++++++++ .../response/ResponseAlertExpirationDate.java | 7 +++++++ .../service/ingredient/IngredientService.java | 2 ++ .../service/ingredient/IngredientServiceImpl.java | 10 ++++++++++ 5 files changed, 37 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestAlertExpirationDate.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 7e78ac9..06b3dff 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -88,4 +88,14 @@ public ResponseEntity deleteIngredientBookmark return ResponseEntity.status(HttpStatus.OK).body(responseDeleteIngredientBookmark); } + @GetMapping("/alert") + public ResponseEntity alertExpirationDate( + @RequestBody RequestAlertExpirationDate requestAlertExpirationDate + ) { + ResponseAlertExpirationDate responseAlertExpirationDate = + ingredientService.alertExpirationDate(requestAlertExpirationDate); + + return ResponseEntity.status(HttpStatus.OK).body(responseAlertExpirationDate); + } + } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestAlertExpirationDate.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestAlertExpirationDate.java new file mode 100644 index 0000000..dec0816 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/request/RequestAlertExpirationDate.java @@ -0,0 +1,8 @@ +package moja.refrigerator.dto.ingredient.request; + +import lombok.Data; + +@Data +public class RequestAlertExpirationDate { + private long userPk; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java new file mode 100644 index 0000000..f2c05d3 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java @@ -0,0 +1,7 @@ +package moja.refrigerator.dto.ingredient.response; + +import lombok.Data; + +@Data +public class ResponseAlertExpirationDate { +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index c73c9aa..e163085 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -20,4 +20,6 @@ List getUsersIngredientBookmarkLists( RequestIngredientBookmarkLists requestBookmarkLists); ResponseDeleteIngredientBookmark deleteIngredientBookmark(RequestDeleteIngredientBookmark requestDeleteBookmark); + + ResponseAlertExpirationDate alertExpirationDate(RequestAlertExpirationDate requestAlertExpirationDate); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index 3b25f4f..adf985a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -180,4 +180,14 @@ public ResponseDeleteIngredientBookmark deleteIngredientBookmark( return response; } } + + @Override + public ResponseAlertExpirationDate alertExpirationDate( + RequestAlertExpirationDate requestAlertExpirationDate) { + // 1. 현재일 찾기 + // 2. 내 냉장고 전채 조회 + // 3. 남은 유통기한 계산 + // 4. 리턴 + return null; + } } From 8184f3b8239867478aaefaf07d61d17f986b9a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=ED=9D=AC=EC=A4=80?= Date: Mon, 16 Dec 2024 13:42:19 +0900 Subject: [PATCH 38/46] =?UTF-8?q?=20Refactor=20:=20Response=20=EC=97=90=20?= =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=9E=AC=EB=A3=8C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=201.=20=EB=A0=88=EC=8B=9C=ED=94=BC=EC=97=90=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A0=84=EC=B2=B4=20=EC=9E=AC?= =?UTF-8?q?=EB=A3=8C=EB=8F=84=20=EA=B0=80=EC=A0=B8=EC=98=B4=202.=20?= =?UTF-8?q?=ED=95=84=EC=88=98=EC=9E=AC=EB=A3=8C=20=EC=9D=B8=EC=A7=80?= =?UTF-8?q?=EB=8A=94=20boolean=20=EC=9C=BC=EB=A1=9C=20=EA=B5=AC=EB=B3=84?= =?UTF-8?q?=20Related=20to=20:=20#19-2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recipe/response/RecipeIngredientInfo.java | 9 ++++++++ .../response/RecipeRecommendResponse.java | 3 +++ .../service/recipe/RecipeServiceImpl.java | 21 +++++++++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeIngredientInfo.java diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeIngredientInfo.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeIngredientInfo.java new file mode 100644 index 0000000..fecc03b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeIngredientInfo.java @@ -0,0 +1,9 @@ +package moja.refrigerator.dto.recipe.response; + +import lombok.Data; + +@Data +public class RecipeIngredientInfo { + private String ingredientName; + private boolean isNecessary; +} \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java index dbb6019..efdb622 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java @@ -2,6 +2,8 @@ import lombok.Data; +import java.util.List; + @Data public class RecipeRecommendResponse { private long recipePk; @@ -11,4 +13,5 @@ public class RecipeRecommendResponse { private double matchRate; private long remainExpirationDays; private String urgentIngredientName; + private List ingredients; } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index e8747bc..e54afe6 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -10,6 +10,7 @@ import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeIngredientInfo; import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.ingredient.IngredientMyRefrigeratorRepository; @@ -318,24 +319,32 @@ private RecipeMatchResult checkRecipeMatch(Recipe recipe, List allRecipes = recipeRepository.findAll(); - // 2. 레시피가 없는 경우 예외 처리 if (allRecipes.isEmpty()) { throw new IllegalStateException("등록된 레시피가 없습니다."); } - // 3. 랜덤 인덱스 생성 Random random = new Random(); int randomIndex = random.nextInt(allRecipes.size()); - - // 4. 랜덤하게 선택된 레시피 Recipe selectedRecipe = allRecipes.get(randomIndex); - // 5. Response 객체로 변환 + // Response 객체로 변환 RecipeRecommendResponse response = mapper.map(selectedRecipe, RecipeRecommendResponse.class); + // 재료 정보 추가 + List recipeIngredients = recipeIngredientRepository.findByRecipe(selectedRecipe); + List ingredientInfoList = recipeIngredients.stream() + .map(ri -> { + RecipeIngredientInfo info = new RecipeIngredientInfo(); + info.setIngredientName(ri.getIngredientManagement().getIngredientName()); + info.setNecessary(ri.isIngredientIsNecessary()); + return info; + }) + .collect(Collectors.toList()); + + response.setIngredients(ingredientInfoList); + return response; } From 3ffe884b6be60ae1847d705c3afe8fffc2c0f09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Mon, 16 Dec 2024 15:07:03 +0900 Subject: [PATCH 39/46] =?UTF-8?q?Feat:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TokenBlacklist 엔티티 및 Repository 생성 - LogoutFilter를 통한 로그아웃 처리 구현 - SecurityConfig에 로그아웃 설정 추가 - JWTFilter에 블랙리스트 토큰 검증 로직 추가 Resolves: #38 --- .../.idea/modules/refrigerator.main.iml | 6 ++-- .../aggregate/user/TokenBlacklist.java | 16 +++++++++ .../refrigerator/config/SecurityConfig.java | 28 ++++++++++++--- .../controller/user/UserController.java | 5 ++- .../java/moja/refrigerator/jwt/JWTFilter.java | 11 +++++- .../moja/refrigerator/jwt/LogoutFilter.java | 34 +++++++++++++++++++ .../user/TokenBlacklistRepository.java | 8 +++++ .../service/user/UserService.java | 1 + .../service/user/UserServiceImpl.java | 8 +++-- 9 files changed, 106 insertions(+), 11 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/user/TokenBlacklist.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/jwt/LogoutFilter.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/user/TokenBlacklistRepository.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index ac8e328..397c268 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,6 +1,9 @@ + + + @@ -17,5 +20,4 @@ - - + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/TokenBlacklist.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/TokenBlacklist.java new file mode 100644 index 0000000..fc72650 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/TokenBlacklist.java @@ -0,0 +1,16 @@ +package moja.refrigerator.aggregate.user; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "tbl_token_blacklist") +@Data +public class TokenBlacklist { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long blacklistPk; + + @Column(nullable = false) + private String blacklistToken; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 462533f..44053ca 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -1,8 +1,11 @@ package moja.refrigerator.config; +import jakarta.servlet.http.HttpServletResponse; import moja.refrigerator.jwt.JWTFilter; import moja.refrigerator.jwt.JWTUtil; import moja.refrigerator.jwt.LoginFilter; +import moja.refrigerator.jwt.LogoutFilter; +import moja.refrigerator.repository.user.TokenBlacklistRepository; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -21,10 +24,14 @@ public class SecurityConfig { private final AuthenticationConfiguration authenticationConfiguration; // JWTUtil 주입 private final JWTUtil jwtUtil; + private final LogoutFilter logoutFilter; + private final TokenBlacklistRepository tokenBlacklistRepository; - public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil) { + public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, LogoutFilter logoutFilter, TokenBlacklistRepository tokenBlacklistRepository) { this.authenticationConfiguration = authenticationConfiguration; this.jwtUtil = jwtUtil; + this.logoutFilter = logoutFilter; + this.tokenBlacklistRepository = tokenBlacklistRepository; } @Bean @@ -56,8 +63,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // URL 별 접근 권한 설정 http .authorizeHttpRequests((auth) -> auth - .requestMatchers("/**").permitAll() // 이 경로들은 모두 접근 가능 - .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 +// .requestMatchers("/**").permitAll() // 이 경로들은 모두 접근 가능 +// .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 // 세션 관리 설정 @@ -66,11 +73,22 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); // JWT 사용을 위한 세션리스 설정 // 로그인 필터 추가 - http - .addFilterBefore(new JWTFilter(jwtUtil), LoginFilter.class); http .addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil), UsernamePasswordAuthenticationFilter.class); + http + .addFilterAfter(new JWTFilter(jwtUtil, tokenBlacklistRepository), LoginFilter.class); + + http + .logout(logout -> logout + .logoutUrl("/logout") + .addLogoutHandler(logoutFilter) + .logoutSuccessHandler((request, response, authentication) -> { + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().write("로그아웃 되었습니다."); + })); + return http.build(); } } \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index 7adacab..97692a3 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -1,7 +1,9 @@ package moja.refrigerator.controller.user; +import jakarta.servlet.http.HttpServletRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.service.user.UserService; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -23,7 +25,8 @@ public String getMainPage() { // 회원 가입 처리 @PostMapping("/auth/join") - public void joinProcess(@RequestBody UserCreateRequest request) { + public ResponseEntity join(@RequestBody UserCreateRequest request) { userService.createUser(request); + return ResponseEntity.ok().body("회원가입이 완료되었습니다."); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java b/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java index e22cfe8..a0b4677 100644 --- a/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/JWTFilter.java @@ -6,6 +6,7 @@ import jakarta.servlet.http.HttpServletResponse; import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.user.CustomUserDetails; +import moja.refrigerator.repository.user.TokenBlacklistRepository; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -15,9 +16,11 @@ public class JWTFilter extends OncePerRequestFilter { private final JWTUtil jwtUtil; + private final TokenBlacklistRepository tokenBlacklistRepository; - public JWTFilter(JWTUtil jwtUtil) { + public JWTFilter(JWTUtil jwtUtil, TokenBlacklistRepository tokenBlacklistRepository) { this.jwtUtil = jwtUtil; + this.tokenBlacklistRepository = tokenBlacklistRepository; } @Override @@ -33,6 +36,12 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse String token = authorization.split(" ")[1]; + // 블랙리스트 체크 + if (tokenBlacklistRepository.existsByBlacklistToken(token)) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + // 토큰 소멸 시간 검증 if (jwtUtil.isExpired(token)) { // 만료된 토큰이면 그냥 통과 diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/LogoutFilter.java b/refrigerator/src/main/java/moja/refrigerator/jwt/LogoutFilter.java new file mode 100644 index 0000000..971f73d --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/LogoutFilter.java @@ -0,0 +1,34 @@ +package moja.refrigerator.jwt; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import moja.refrigerator.aggregate.user.TokenBlacklist; +import moja.refrigerator.repository.user.TokenBlacklistRepository; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.stereotype.Component; + +@Component +public class LogoutFilter implements LogoutHandler { + private final TokenBlacklistRepository tokenBlacklistRepository; + + public LogoutFilter(TokenBlacklistRepository tokenBlacklistRepository) { + this.tokenBlacklistRepository = tokenBlacklistRepository; + } + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + String authorization = request.getHeader("Authorization"); + + if (authorization == null || !authorization.startsWith("Bearer ")) { + throw new IllegalArgumentException("토큰이 유효하지 않습니다."); + } + + String token = authorization.split(" ")[1]; + + // 토큰을 블랙리스트에 추가 + TokenBlacklist blacklist = new TokenBlacklist(); + blacklist.setBlacklistToken(token); + tokenBlacklistRepository.save(blacklist); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/TokenBlacklistRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/TokenBlacklistRepository.java new file mode 100644 index 0000000..6d82bd7 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/TokenBlacklistRepository.java @@ -0,0 +1,8 @@ +package moja.refrigerator.repository.user; + +import moja.refrigerator.aggregate.user.TokenBlacklist; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TokenBlacklistRepository extends JpaRepository { + boolean existsByBlacklistToken(String blacklistToken); +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java index 80fa52c..a3cc1fa 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java @@ -1,5 +1,6 @@ package moja.refrigerator.service.user; +import jakarta.servlet.http.HttpServletRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; public interface UserService { diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 7cd888b..0bbb720 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -1,8 +1,11 @@ package moja.refrigerator.service.user; +import jakarta.servlet.http.HttpServletRequest; +import moja.refrigerator.aggregate.user.TokenBlacklist; import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.exception.user.DuplicateUserException; +import moja.refrigerator.repository.user.TokenBlacklistRepository; import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -17,11 +20,13 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final BCryptPasswordEncoder passwordEncoder; private final ModelMapper modelMapper; + private final TokenBlacklistRepository tokenBlacklistRepository; - public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper) { + public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper, TokenBlacklistRepository tokenBlacklistRepository) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; this.modelMapper = modelMapper; + this.tokenBlacklistRepository = tokenBlacklistRepository; } @Override @@ -40,7 +45,6 @@ public void createUser(UserCreateRequest request) { userRepository.save(user); } - private void checkDuplicateUser(UserCreateRequest request) { List errors = new ArrayList<>(); if (userRepository.existsByUserId(request.getUserId())) { From 6baa83384c7ac7954ee2416fb82d018668ef5ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Mon, 16 Dec 2024 15:15:00 +0900 Subject: [PATCH 40/46] =?UTF-8?q?Chore:=20URL=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/moja/refrigerator/config/SecurityConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java index 44053ca..f42e6c7 100644 --- a/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java +++ b/refrigerator/src/main/java/moja/refrigerator/config/SecurityConfig.java @@ -63,8 +63,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // URL 별 접근 권한 설정 http .authorizeHttpRequests((auth) -> auth -// .requestMatchers("/**").permitAll() // 이 경로들은 모두 접근 가능 -// .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 + .requestMatchers("/**").permitAll() // 이 경로들은 모두 접근 가능 + .requestMatchers("/admin").hasRole("ADMIN") // admin 경로는 ADMIN 역할을 가진 사용자만 .anyRequest().authenticated()); // 나머지는 인증된 사용자만 // 세션 관리 설정 From 88103ec9881d875d9525db4af1bc22498561fe8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=ED=9D=AC=EC=A4=80?= Date: Mon, 16 Dec 2024 17:10:08 +0900 Subject: [PATCH 41/46] =?UTF-8?q?=20Feat=20:=20=EB=A0=88=EC=8B=9C=ED=94=BC?= =?UTF-8?q?=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94=20?= =?UTF-8?q?1.=20=EA=B0=81=20=EB=A0=88=EC=8B=9C=ED=94=BC=EB=B3=84=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94?= =?UTF-8?q?=EB=A5=BC=20=ED=9A=8C=EC=9B=90=EB=8B=B9=20=ED=95=9C=20=EA=B0=80?= =?UTF-8?q?=EC=A7=80=20=EC=84=A0=ED=83=9D=20=EA=B0=80=EB=8A=A5=20(=20null?= =?UTF-8?q?=20=EB=8F=84=20=EC=9E=88=EC=96=B4=EC=84=9C=20=EC=95=88=20?= =?UTF-8?q?=EB=88=84=EB=A5=BC=20=EC=88=98=20=EC=9E=88=EB=8B=A4)=202.=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94=20?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EA=B3=84=EC=82=B0=ED=95=9C=EA=B0=92?= =?UTF-8?q?=EC=9D=B4=20=EB=82=98=EC=98=A8=EB=8B=A4.=20Related=20to=20:=20#?= =?UTF-8?q?20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.idea/modules/refrigerator.main.iml | 19 ++------ .../aggregate/recipe/RecipeLikeDislike.java | 27 +++++++++++ .../controller/recipe/RecipeController.java | 10 +++++ .../dto/recipe/request/RecipeLikeRequest.java | 10 +++++ .../recipe/response/RecipeLikeResponse.java | 12 +++++ .../recipe/RecipeLikeDislikeRepository.java | 14 ++++++ .../service/recipe/RecipeService.java | 3 ++ .../service/recipe/RecipeServiceImpl.java | 45 ++++++++++++++++--- 8 files changed, 118 insertions(+), 22 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index ac8e328..afc1871 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,21 +1,8 @@ - - + + - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java new file mode 100644 index 0000000..8fe52a5 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeLikeDislike.java @@ -0,0 +1,27 @@ +package moja.refrigerator.aggregate.recipe; + +import jakarta.persistence.*; +import lombok.Data; +import moja.refrigerator.aggregate.user.User; + +@Entity +@Table(name = "tbl_recipe_like_dislike") +@Data +public class RecipeLikeDislike { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "like_dislike_pk") + private Long id; + + @ManyToOne + @JoinColumn(name = "recipe_pk") + private Recipe recipe; + + @ManyToOne + @JoinColumn(name = "user_pk") + private User user; + + @Column(name = "like_status") + private Boolean likeStatus; +} + diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java index d332f82..03ecb0a 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java @@ -2,8 +2,10 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeLikeRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeLikeResponse; import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.service.recipe.RecipeService; @@ -69,4 +71,12 @@ public ResponseEntity getRandomRecipe() { return ResponseEntity.notFound().build(); } } + + @PostMapping("/reaction") + public ResponseEntity toggleLikeDislike( + @RequestBody RecipeLikeRequest request + ) { + return ResponseEntity.ok(recipeService.toggleLikeDislike(request)); + } + } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java new file mode 100644 index 0000000..4deff9c --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/request/RecipeLikeRequest.java @@ -0,0 +1,10 @@ +package moja.refrigerator.dto.recipe.request; + +import lombok.Data; + +@Data +public class RecipeLikeRequest { + private Long recipePk; + private Long userPk; + private Boolean likeStatus; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java new file mode 100644 index 0000000..a104acf --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeLikeResponse.java @@ -0,0 +1,12 @@ +package moja.refrigerator.dto.recipe.response; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class RecipeLikeResponse { + private long likesCount; + private long dislikesCount; + private Boolean userReaction; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java new file mode 100644 index 0000000..7510915 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeLikeDislikeRepository.java @@ -0,0 +1,14 @@ +package moja.refrigerator.repository.recipe; + +import moja.refrigerator.aggregate.recipe.Recipe; +import moja.refrigerator.aggregate.recipe.RecipeLikeDislike; +import moja.refrigerator.aggregate.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.Optional; + +@Repository +public interface RecipeLikeDislikeRepository extends JpaRepository { + Optional findByRecipeAndUser(Recipe recipe, User user); + long countByRecipeAndLikeStatus(Recipe recipe, Boolean likeStatus); +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java index cb89a94..81c69a5 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java @@ -2,8 +2,10 @@ import moja.refrigerator.aggregate.recipe.Recipe; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeLikeRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; +import moja.refrigerator.dto.recipe.response.RecipeLikeResponse; import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; import moja.refrigerator.dto.recipe.response.RecipeResponse; import moja.refrigerator.repository.recipe.RecipeRepository; @@ -25,4 +27,5 @@ void updateRecipe( ); List getRecommendedRecipes(Long userPk); RecipeRecommendResponse getRandomRecipe(); + RecipeLikeResponse toggleLikeDislike(RecipeLikeRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java index e54afe6..42030fb 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java @@ -8,11 +8,9 @@ import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.recipe.RecipeMatchResult; import moja.refrigerator.dto.recipe.request.RecipeCreateRequest; +import moja.refrigerator.dto.recipe.request.RecipeLikeRequest; import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest; -import moja.refrigerator.dto.recipe.response.RecipeDetailResponse; -import moja.refrigerator.dto.recipe.response.RecipeIngredientInfo; -import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse; -import moja.refrigerator.dto.recipe.response.RecipeResponse; +import moja.refrigerator.dto.recipe.response.*; import moja.refrigerator.repository.ingredient.IngredientMyRefrigeratorRepository; import moja.refrigerator.repository.recipe.*; import moja.refrigerator.repository.user.UserRepository; @@ -43,6 +41,7 @@ public class RecipeServiceImpl implements RecipeService { private final IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository; private final RecipeIngredientRepository recipeIngredientRepository; private final ReplacableIngredientRepository replacableIngredientRepository; + private final RecipeLikeDislikeRepository recipeLikeDislikeRepository; @Value("${cloud.aws.s3.bucket}") private String bucket; @@ -58,7 +57,8 @@ public RecipeServiceImpl( AmazonS3Client amazonS3Client, IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository, RecipeIngredientRepository recipeIngredientRepository, - ReplacableIngredientRepository replacableIngredientRepository + ReplacableIngredientRepository replacableIngredientRepository, + RecipeLikeDislikeRepository recipeLikeDislikeRepository ) { this.recipeRepository = recipeRepository; this.userRepository = userRepository; @@ -70,8 +70,8 @@ public RecipeServiceImpl( this.ingredientMyRefrigeratorRepository = ingredientMyRefrigeratorRepository; this.recipeIngredientRepository = recipeIngredientRepository; this.replacableIngredientRepository = replacableIngredientRepository; + this.recipeLikeDislikeRepository = recipeLikeDislikeRepository; } - private boolean isImageFile(String fileName) { String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); return List.of("jpg", "jpeg", "png", "gif").contains(extension); @@ -348,4 +348,37 @@ public RecipeRecommendResponse getRandomRecipe() { return response; } + @Override + @Transactional + public RecipeLikeResponse toggleLikeDislike(RecipeLikeRequest request) { + Recipe recipe = recipeRepository.findById(request.getRecipePk()) + .orElseThrow(() -> new IllegalArgumentException("레시피를 찾을 수 없습니다.")); + + User user = userRepository.findById(request.getUserPk()) + .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + + Optional existing = + recipeLikeDislikeRepository.findByRecipeAndUser(recipe, user); + + if (existing.isPresent()) { + if (existing.get().getLikeStatus() == request.getLikeStatus()) { + recipeLikeDislikeRepository.delete(existing.get()); + } else { + existing.get().setLikeStatus(request.getLikeStatus()); + } + } else { + RecipeLikeDislike newReaction = new RecipeLikeDislike(); + newReaction.setRecipe(recipe); + newReaction.setUser(user); + newReaction.setLikeStatus(request.getLikeStatus()); + recipeLikeDislikeRepository.save(newReaction); + } + + // 현재 좋아요/싫어요 수 계산 + long likes = recipeLikeDislikeRepository.countByRecipeAndLikeStatus(recipe, true); + long dislikes = recipeLikeDislikeRepository.countByRecipeAndLikeStatus(recipe, false); + + return new RecipeLikeResponse(likes, dislikes, request.getLikeStatus()); + } + } \ No newline at end of file From c4e27f31dd7a67148b694e9353ec328223813985 Mon Sep 17 00:00:00 2001 From: yunjaeeun Date: Mon, 16 Dec 2024 17:37:54 +0900 Subject: [PATCH 42/46] =?UTF-8?q?Feat:=20=EC=9C=A0=ED=86=B5=EA=B8=B0?= =?UTF-8?q?=ED=95=9C=20=EC=95=8C=EB=9E=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 남은 유통기한 알람 구현 완료 유통기한이 7일, 3일 남은 상품에 대해서 알람 발송 2. 로그인 시 작동되도록 수정 필요 Related to: #17 --- .../ingredient/IngredientController.java | 4 +- .../response/ResponseAlertExpirationDate.java | 14 +++++++ .../service/ingredient/IngredientService.java | 2 +- .../ingredient/IngredientServiceImpl.java | 37 ++++++++++++++++--- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java index 06b3dff..0333c74 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/ingredient/IngredientController.java @@ -89,10 +89,10 @@ public ResponseEntity deleteIngredientBookmark } @GetMapping("/alert") - public ResponseEntity alertExpirationDate( + public ResponseEntity> alertExpirationDate( @RequestBody RequestAlertExpirationDate requestAlertExpirationDate ) { - ResponseAlertExpirationDate responseAlertExpirationDate = + List responseAlertExpirationDate = ingredientService.alertExpirationDate(requestAlertExpirationDate); return ResponseEntity.status(HttpStatus.OK).body(responseAlertExpirationDate); diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java index f2c05d3..e69430d 100644 --- a/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java +++ b/refrigerator/src/main/java/moja/refrigerator/dto/ingredient/response/ResponseAlertExpirationDate.java @@ -1,7 +1,21 @@ package moja.refrigerator.dto.ingredient.response; import lombok.Data; +import moja.refrigerator.aggregate.ingredient.IngredientManagement; @Data public class ResponseAlertExpirationDate { + private long ingredientMyRefrigeratorPk; + private IngredientManagement ingredientManagement; + private float ingredientAmount; + private String expirationDate; + private int remainDate; + + public ResponseAlertExpirationDate(long ingredientMyRefrigeratorPk, IngredientManagement ingredientManagement, float ingredientAmount, String expirationDate, int remainDate) { + this.ingredientMyRefrigeratorPk = ingredientMyRefrigeratorPk; + this.ingredientManagement = ingredientManagement; + this.ingredientAmount = ingredientAmount; + this.expirationDate = expirationDate; + this.remainDate = remainDate; + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java index e163085..882ac06 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientService.java @@ -21,5 +21,5 @@ List getUsersIngredientBookmarkLists( ResponseDeleteIngredientBookmark deleteIngredientBookmark(RequestDeleteIngredientBookmark requestDeleteBookmark); - ResponseAlertExpirationDate alertExpirationDate(RequestAlertExpirationDate requestAlertExpirationDate); + List alertExpirationDate(RequestAlertExpirationDate requestAlertExpirationDate); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java index adf985a..9842b63 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/ingredient/IngredientServiceImpl.java @@ -16,11 +16,10 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; -import java.util.Comparator; -import java.util.List; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -import java.util.Optional; import java.util.stream.Collectors; @Service @@ -182,12 +181,40 @@ public ResponseDeleteIngredientBookmark deleteIngredientBookmark( } @Override - public ResponseAlertExpirationDate alertExpirationDate( + public List alertExpirationDate( RequestAlertExpirationDate requestAlertExpirationDate) { // 1. 현재일 찾기 + LocalDate currentDate = LocalDate.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 원하는 포맷 지정 + String dateString = currentDate.format(formatter); + // 2. 내 냉장고 전채 조회 + List refrigeratorList = ingredientMyRefrigeratorRepository + .findByUserUserPk(requestAlertExpirationDate.getUserPk()); + + List responseAlertExpirationDates = new ArrayList<>(); // 3. 남은 유통기한 계산 + for (IngredientMyRefrigerator ingredientMyRefrigerator : refrigeratorList) { + LocalDate expirationDate = LocalDate.parse(ingredientMyRefrigerator.getExpirationDate(), formatter); + + long daysUntilExpiration = ChronoUnit.DAYS.between(currentDate, expirationDate); + + if (daysUntilExpiration == 7 || daysUntilExpiration == 3) { + // ResponseAlertExpirationDate 객체 생성 + ResponseAlertExpirationDate response = new ResponseAlertExpirationDate( + ingredientMyRefrigerator.getIngredientMyRefrigeratorPk(), + ingredientMyRefrigerator.getIngredientManagement(), + ingredientMyRefrigerator.getIngredientAmount(), + ingredientMyRefrigerator.getExpirationDate(), + (int) daysUntilExpiration // daysUntilExpiration을 int로 변환 + ); + + // 리스트에 추가 + responseAlertExpirationDates.add(response); + } + + } // 4. 리턴 - return null; + return responseAlertExpirationDates; } } From 7d6aecfb22e0be8b5089296e5d4103cf46ffb54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Mon, 16 Dec 2024 20:08:56 +0900 Subject: [PATCH 43/46] =?UTF-8?q?Feat:=20=ED=9A=8C=EC=9B=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UserUpdateRequest DTO 생성 - UserController에 회원 정보 수정 API 추가 - UserService에 updateUser 메서드 구현 - 로그인된 사용자 본인의 정보만 수정 가능 - 이메일, 닉네임 중 선택적으로 수정 가능 Resolves: #43 --- .../controller/user/UserController.java | 15 ++++--- .../dto/user/request/UserUpdateRequest.java | 9 +++++ .../moja/refrigerator/jwt/LoginFilter.java | 2 +- .../service/user/UserService.java | 3 +- .../service/user/UserServiceImpl.java | 39 ++++++++++++++++--- 5 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserUpdateRequest.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index 97692a3..cbd031e 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -2,12 +2,10 @@ import jakarta.servlet.http.HttpServletRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; +import moja.refrigerator.dto.user.request.UserUpdateRequest; import moja.refrigerator.service.user.UserService; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController public class UserController { @@ -27,6 +25,13 @@ public String getMainPage() { @PostMapping("/auth/join") public ResponseEntity join(@RequestBody UserCreateRequest request) { userService.createUser(request); - return ResponseEntity.ok().body("회원가입이 완료되었습니다."); + return ResponseEntity.ok().body("회원 가입이 완료되었습니다."); + } + + // 회원 정보 수정 + @PutMapping("/update") + public ResponseEntity update(@RequestBody UserUpdateRequest request) { + userService.updateUser(request); + return ResponseEntity.ok().body("회원 정보가 수정되었습니다."); } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserUpdateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserUpdateRequest.java new file mode 100644 index 0000000..22289eb --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/UserUpdateRequest.java @@ -0,0 +1,9 @@ +package moja.refrigerator.dto.user.request; + +import lombok.Data; + +@Data +public class UserUpdateRequest { + private String userEmail; + private String userNickname; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java b/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java index 622aac9..17f3ed5 100644 --- a/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java +++ b/refrigerator/src/main/java/moja/refrigerator/jwt/LoginFilter.java @@ -50,7 +50,7 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR String role = auth.getAuthority(); - String token = jwtUtil.createJwt(username, role, 60*60*10L); + String token = jwtUtil.createJwt(username, role, 60*60*10*1000L); response.addHeader("Authorization", "Bearer " + token); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java index a3cc1fa..9109d98 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java @@ -1,8 +1,9 @@ package moja.refrigerator.service.user; -import jakarta.servlet.http.HttpServletRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; +import moja.refrigerator.dto.user.request.UserUpdateRequest; public interface UserService { void createUser(UserCreateRequest request); + void updateUser(UserUpdateRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 0bbb720..5309804 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -1,13 +1,15 @@ package moja.refrigerator.service.user; -import jakarta.servlet.http.HttpServletRequest; -import moja.refrigerator.aggregate.user.TokenBlacklist; import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.user.request.UserCreateRequest; +import moja.refrigerator.dto.user.request.UserUpdateRequest; import moja.refrigerator.exception.user.DuplicateUserException; import moja.refrigerator.repository.user.TokenBlacklistRepository; import moja.refrigerator.repository.user.UserRepository; import org.modelmapper.ModelMapper; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,13 +22,11 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final BCryptPasswordEncoder passwordEncoder; private final ModelMapper modelMapper; - private final TokenBlacklistRepository tokenBlacklistRepository; - public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper, TokenBlacklistRepository tokenBlacklistRepository) { + public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; this.modelMapper = modelMapper; - this.tokenBlacklistRepository = tokenBlacklistRepository; } @Override @@ -45,6 +45,35 @@ public void createUser(UserCreateRequest request) { userRepository.save(user); } + @Override + @Transactional + public void updateUser(UserUpdateRequest request) { + // 현재 로그인한 사용자 정보 가져오기 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String userId = authentication.getName(); + + User user = userRepository.findByUserId(userId) + .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다.")); + + // 이메일 변경 요청이 있는 경우 + if (request.getUserEmail() != null) { + if (!request.getUserEmail().equals(user.getUserEmail()) + && userRepository.existsByUserEmail(request.getUserEmail())) { + throw new DuplicateUserException("이미 사용 중인 이메일입니다."); + } + user.setUserEmail(request.getUserEmail()); + } + + // 닉네임 변경 요청이 있는 경우 + if (request.getUserNickname() != null) { + if (!request.getUserNickname().equals(user.getUserNickname()) + && userRepository.existsByUserNickname(request.getUserNickname())) { + throw new DuplicateUserException("이미 사용 중인 닉네임입니다."); + } + user.setUserNickname(request.getUserNickname()); + } + } + private void checkDuplicateUser(UserCreateRequest request) { List errors = new ArrayList<>(); if (userRepository.existsByUserId(request.getUserId())) { From 0c3e783f69502c5ff251a2e1763aba3d22120df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Tue, 17 Dec 2024 12:15:39 +0900 Subject: [PATCH 44/46] =?UTF-8?q?Feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=AC=EB=B0=9C=EA=B8=89=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이메일 전송을 위한 의존성 추가 - EmailService에 이메일 전송을 위한 로직 구현 - UserService의 resetPassword 메서드에서 임시 비밀번호 생성 Related to: #47 --- .../.idea/modules/refrigerator.main.iml | 6 ++- refrigerator/build.gradle | 2 + .../controller/user/UserController.java | 11 +++++- .../user/request/PasswordResetRequest.java | 8 ++++ .../repository/user/UserRepository.java | 1 + .../service/email/EmailService.java | 5 +++ .../service/email/EmailServiceImpl.java | 38 +++++++++++++++++++ .../service/user/UserService.java | 2 + .../service/user/UserServiceImpl.java | 35 +++++++++++++---- 9 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml index ac8e328..397c268 100644 --- a/refrigerator/.idea/modules/refrigerator.main.iml +++ b/refrigerator/.idea/modules/refrigerator.main.iml @@ -1,6 +1,9 @@ + + + @@ -17,5 +20,4 @@ - - + \ No newline at end of file diff --git a/refrigerator/build.gradle b/refrigerator/build.gradle index bc46bee..156aa6d 100644 --- a/refrigerator/build.gradle +++ b/refrigerator/build.gradle @@ -41,6 +41,8 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' testImplementation 'org.springframework.boot:spring-boot-starter-test' + + implementation 'org.springframework.boot:spring-boot-starter-mail' } tasks.named('test') { useJUnitPlatform() diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index cbd031e..9ac8062 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -1,9 +1,11 @@ package moja.refrigerator.controller.user; import jakarta.servlet.http.HttpServletRequest; +import moja.refrigerator.dto.user.request.PasswordResetRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; import moja.refrigerator.service.user.UserService; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -25,7 +27,7 @@ public String getMainPage() { @PostMapping("/auth/join") public ResponseEntity join(@RequestBody UserCreateRequest request) { userService.createUser(request); - return ResponseEntity.ok().body("회원 가입이 완료되었습니다."); + return ResponseEntity.status(HttpStatus.CREATED).body("회원 가입이 완료되었습니다."); } // 회원 정보 수정 @@ -34,4 +36,11 @@ public ResponseEntity update(@RequestBody UserUpdateRequest request) { userService.updateUser(request); return ResponseEntity.ok().body("회원 정보가 수정되었습니다."); } + + // 비밀번호 재발급 + @PostMapping("/password/reset") + public ResponseEntity resetPassword(@RequestBody PasswordResetRequest request) { + userService.resetPassword(request); + return ResponseEntity.ok().body("임시 비밀번호가 이메일로 발송되었습니다."); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java new file mode 100644 index 0000000..89b2c75 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordResetRequest.java @@ -0,0 +1,8 @@ +package moja.refrigerator.dto.user.request; + +import lombok.Data; + +@Data +public class PasswordResetRequest { + private String userEmail; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java index b3b44c0..1742c4b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/UserRepository.java @@ -13,4 +13,5 @@ public interface UserRepository extends JpaRepository { boolean existsByUserNickname(String userNickname); Optional findByUserPk(long userPk); Optional findByUserId(String userId); + Optional findByUserEmail(String userEmail); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java new file mode 100644 index 0000000..c189c53 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailService.java @@ -0,0 +1,5 @@ +package moja.refrigerator.service.email; + +public interface EmailService { + void sendTempPassword(String name, String email, String tempPassword); +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java new file mode 100644 index 0000000..ec915b3 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/email/EmailServiceImpl.java @@ -0,0 +1,38 @@ +package moja.refrigerator.service.email; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class EmailServiceImpl implements EmailService { + private final JavaMailSender mailSender; + + public EmailServiceImpl(JavaMailSender mailSender) { + this.mailSender = mailSender; + } + + @Value("${spring.mail.username}") + private String senderEmail; + + @Override + @Transactional + public void sendTempPassword(String name, String email, String tempPassword) { + SimpleMailMessage message = new SimpleMailMessage(); + + message.setTo(email); + message.setFrom(senderEmail); + message.setSubject("[ReciPick] 임시 비밀번호 발급"); + message.setText(String.format(""" + 안녕하세요. %s님! 임시 비밀번호가 발급되었습니다. + + 임시 비밀번호: %s + + 보안을 위해 로그인 후 반드시 비밀번호를 변경해 주세요. + """, name, tempPassword)); + + mailSender.send(message); + } +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java index 9109d98..ed79a4b 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java @@ -1,9 +1,11 @@ package moja.refrigerator.service.user; +import moja.refrigerator.dto.user.request.PasswordResetRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; public interface UserService { void createUser(UserCreateRequest request); void updateUser(UserUpdateRequest request); + void resetPassword(PasswordResetRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 5309804..3188472 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -1,11 +1,13 @@ package moja.refrigerator.service.user; +import lombok.RequiredArgsConstructor; import moja.refrigerator.aggregate.user.User; +import moja.refrigerator.dto.user.request.PasswordResetRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; import moja.refrigerator.exception.user.DuplicateUserException; -import moja.refrigerator.repository.user.TokenBlacklistRepository; import moja.refrigerator.repository.user.UserRepository; +import moja.refrigerator.service.email.EmailService; import org.modelmapper.ModelMapper; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -16,18 +18,15 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; @Service +@RequiredArgsConstructor public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final BCryptPasswordEncoder passwordEncoder; private final ModelMapper modelMapper; - - public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder, ModelMapper modelMapper) { - this.userRepository = userRepository; - this.passwordEncoder = passwordEncoder; - this.modelMapper = modelMapper; - } + private final EmailService emailService; @Override @Transactional @@ -74,6 +73,28 @@ public void updateUser(UserUpdateRequest request) { } } + @Override + @Transactional + public void resetPassword(PasswordResetRequest request) { + // 이메일로 사용자 찾기 + User user = userRepository.findByUserEmail(request.getUserEmail()) + .orElseThrow(() -> new UsernameNotFoundException("해당 이메일로 가입된 계정이 없습니다.")); + + // 임시 비밀번호 생성 + String tempPassword = UUID.randomUUID().toString().substring(0, 12); + + try { + // 이메일 발송 + emailService.sendTempPassword(user.getUserNickname(), user.getUserEmail(), tempPassword); + // 임시 비밀번호로 업데이트 + user.setUserPw(passwordEncoder.encode(tempPassword)); + } catch (Exception e) { + System.out.println("Detailed error: " + e.getMessage()); + throw new RuntimeException("이메일 발송에 실패했습니다."); + } + + } + private void checkDuplicateUser(UserCreateRequest request) { List errors = new ArrayList<>(); if (userRepository.existsByUserId(request.getUserId())) { From e2f463056b6d2ea81ffc9ebfd2f9a7aefbecdcde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Tue, 17 Dec 2024 12:53:05 +0900 Subject: [PATCH 45/46] =?UTF-8?q?Feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PasswordUpdateRequest에서 기존 비밀번호와 새 비밀번호를 받음 - UserService의 updatePassword 메서드에서 비밀번호 변경 - 기존 비밀번호 검증 후 새 비밀번호 저장 Resolves: #47 --- .../controller/user/UserController.java | 8 ++++++++ .../user/request/PasswordUpdateRequest.java | 9 +++++++++ .../service/user/UserService.java | 2 ++ .../service/user/UserServiceImpl.java | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index 9ac8062..3dd637c 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -2,6 +2,7 @@ import jakarta.servlet.http.HttpServletRequest; import moja.refrigerator.dto.user.request.PasswordResetRequest; +import moja.refrigerator.dto.user.request.PasswordUpdateRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; import moja.refrigerator.service.user.UserService; @@ -43,4 +44,11 @@ public ResponseEntity resetPassword(@RequestBody PasswordResetRequest request userService.resetPassword(request); return ResponseEntity.ok().body("임시 비밀번호가 이메일로 발송되었습니다."); } + + // 비밀번호 재설정 + @PutMapping("/password/update") + public ResponseEntity updatePassword(@RequestBody PasswordUpdateRequest request) { + userService.updatePassword(request); + return ResponseEntity.ok().body("비밀번호가 변경되었습니다."); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java new file mode 100644 index 0000000..3b6762a --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/dto/user/request/PasswordUpdateRequest.java @@ -0,0 +1,9 @@ +package moja.refrigerator.dto.user.request; + +import lombok.Data; + +@Data +public class PasswordUpdateRequest { + private String currentPw; + private String newPw; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java index ed79a4b..cfb1abd 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserService.java @@ -1,6 +1,7 @@ package moja.refrigerator.service.user; import moja.refrigerator.dto.user.request.PasswordResetRequest; +import moja.refrigerator.dto.user.request.PasswordUpdateRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; @@ -8,4 +9,5 @@ public interface UserService { void createUser(UserCreateRequest request); void updateUser(UserUpdateRequest request); void resetPassword(PasswordResetRequest request); + void updatePassword(PasswordUpdateRequest request); } diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java index 3188472..7329781 100644 --- a/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/UserServiceImpl.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import moja.refrigerator.aggregate.user.User; import moja.refrigerator.dto.user.request.PasswordResetRequest; +import moja.refrigerator.dto.user.request.PasswordUpdateRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; import moja.refrigerator.exception.user.DuplicateUserException; @@ -95,6 +96,24 @@ public void resetPassword(PasswordResetRequest request) { } + @Override + @Transactional + public void updatePassword(PasswordUpdateRequest request) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String userId = authentication.getName(); + + User user = userRepository.findByUserId(userId) + .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다.")); + + // 기존 비밀번호 검증 + if (!passwordEncoder.matches(request.getCurrentPw(), user.getUserPw())) { + throw new IllegalArgumentException("기존 비밀번호가 일치하지 않습니다."); + } + + // 새 비밀번호 암호화 후 저장 + user.setUserPw(passwordEncoder.encode(request.getNewPw())); + } + private void checkDuplicateUser(UserCreateRequest request) { List errors = new ArrayList<>(); if (userRepository.existsByUserId(request.getUserId())) { From ab073e95833e6e3ff8a182cb032406359f44f19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=A7=80=EB=AF=BC?= Date: Tue, 17 Dec 2024 16:49:08 +0900 Subject: [PATCH 46/46] =?UTF-8?q?Feat:=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 팔로우 상태를 저장할 수 있는 Follow 엔티티 추가 - 로그인한 사용자 정보를 찾은 후 팔로우 하려는 대상 찾음 - 이미 팔로우한 상태라면 언팔로우, 아니라면 팔로우 Resolves: #49 --- .../refrigerator/aggregate/user/Follow.java | 22 ++++++++ .../controller/user/UserController.java | 13 ++++- .../repository/user/FollowRepository.java | 12 +++++ .../service/user/FollowService.java | 5 ++ .../service/user/FollowServiceImpl.java | 50 +++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 refrigerator/src/main/java/moja/refrigerator/aggregate/user/Follow.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/repository/user/FollowRepository.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/user/FollowService.java create mode 100644 refrigerator/src/main/java/moja/refrigerator/service/user/FollowServiceImpl.java diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/user/Follow.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/Follow.java new file mode 100644 index 0000000..80eaa90 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/user/Follow.java @@ -0,0 +1,22 @@ +package moja.refrigerator.aggregate.user; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "tbl_follow") +@Data +public class Follow { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "follow_pk") + private long followPk; + + @ManyToOne + @JoinColumn(name = "follower") + private User follower; + + @ManyToOne + @JoinColumn(name = "following") + private User following; +} diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java index 3dd637c..c841068 100644 --- a/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java +++ b/refrigerator/src/main/java/moja/refrigerator/controller/user/UserController.java @@ -1,10 +1,10 @@ package moja.refrigerator.controller.user; -import jakarta.servlet.http.HttpServletRequest; import moja.refrigerator.dto.user.request.PasswordResetRequest; import moja.refrigerator.dto.user.request.PasswordUpdateRequest; import moja.refrigerator.dto.user.request.UserCreateRequest; import moja.refrigerator.dto.user.request.UserUpdateRequest; +import moja.refrigerator.service.user.FollowService; import moja.refrigerator.service.user.UserService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -13,9 +13,11 @@ @RestController public class UserController { private final UserService userService; + private final FollowService followService; - public UserController(UserService userService) { + public UserController(UserService userService, FollowService followService) { this.userService = userService; + this.followService = followService; } // 토큰 검증 로직 확인용 @@ -51,4 +53,11 @@ public ResponseEntity updatePassword(@RequestBody PasswordUpdateRequest reque userService.updatePassword(request); return ResponseEntity.ok().body("비밀번호가 변경되었습니다."); } + + // 팔로우 및 언팔로우 + @PostMapping("/follow/{userPk}") + public ResponseEntity toggleFollow(@PathVariable Long userPk) { + followService.toggleFollow(userPk); + return ResponseEntity.ok().body("팔로우 상태가 변경되었습니다."); + } } diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/user/FollowRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/user/FollowRepository.java new file mode 100644 index 0000000..a568240 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/repository/user/FollowRepository.java @@ -0,0 +1,12 @@ +package moja.refrigerator.repository.user; + +import moja.refrigerator.aggregate.user.Follow; +import moja.refrigerator.aggregate.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface FollowRepository extends JpaRepository { + boolean existsByFollowerAndFollowing(User follower, User following); + void deleteByFollowerAndFollowing(User follower, User following); +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/FollowService.java b/refrigerator/src/main/java/moja/refrigerator/service/user/FollowService.java new file mode 100644 index 0000000..e213f57 --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/FollowService.java @@ -0,0 +1,5 @@ +package moja.refrigerator.service.user; + +public interface FollowService { + void toggleFollow(Long targetUserPk); +} diff --git a/refrigerator/src/main/java/moja/refrigerator/service/user/FollowServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/user/FollowServiceImpl.java new file mode 100644 index 0000000..14e077b --- /dev/null +++ b/refrigerator/src/main/java/moja/refrigerator/service/user/FollowServiceImpl.java @@ -0,0 +1,50 @@ +package moja.refrigerator.service.user; + +import moja.refrigerator.aggregate.user.Follow; +import moja.refrigerator.aggregate.user.User; +import moja.refrigerator.repository.user.FollowRepository; +import moja.refrigerator.repository.user.UserRepository; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class FollowServiceImpl implements FollowService { + private final FollowRepository followRepository; + private final UserRepository userRepository; + + public FollowServiceImpl(FollowRepository followRepository, UserRepository userRepository) { + this.followRepository = followRepository; + this.userRepository = userRepository; + } + + @Override + @Transactional + public void toggleFollow(Long targetUserPk) { + // 현재 로그인한 사용자 찾기 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + User follower = userRepository.findByUserId(authentication.getName()) + .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다.")); + + // 팔로우 대상 사용자 찾기 + User following = userRepository.findByUserPk(targetUserPk) + .orElseThrow(() -> new UsernameNotFoundException("팔로우 하려는 사용자를 찾을 수 없습니다.")); + + // 자기 자신 팔로우 방지 + if (follower.getUserPk() == following.getUserPk()) { + throw new IllegalArgumentException("자기 자신을 팔로우할 수 없습니다."); + } + + // 이미 팔로우 중이면 언팔로우, 아니면 팔로우 + if (followRepository.existsByFollowerAndFollowing(follower, following)) { + followRepository.deleteByFollowerAndFollowing(follower, following); + } else { + Follow follow = new Follow(); + follow.setFollower(follower); + follow.setFollowing(following); + followRepository.save(follow); + } + } +}