Clean up recipe classes.
This commit is contained in:
parent
70c560f0cb
commit
51cae79daa
@ -93,14 +93,15 @@ public class RecipeControllerTests {
|
||||
}
|
||||
|
||||
private Recipe createTestRecipe(User owner, boolean isPublic) {
|
||||
final RecipeCreateSpec spec = new RecipeCreateSpec();
|
||||
spec.setSlug(UUID.randomUUID().toString());
|
||||
spec.setTitle("Test Recipe");
|
||||
spec.setPreparationTime(10);
|
||||
spec.setCookingTime(20);
|
||||
spec.setTotalTime(30);
|
||||
spec.setRawText("# Hello, World!");
|
||||
spec.setPublic(isPublic);
|
||||
final RecipeCreateSpec spec = RecipeCreateSpec.builder()
|
||||
.slug(UUID.randomUUID().toString())
|
||||
.title("Test Recipe")
|
||||
.preparationTime(10)
|
||||
.cookingTime(20)
|
||||
.totalTime(30)
|
||||
.rawText("# Hello, World!")
|
||||
.isPublic(isPublic)
|
||||
.build();
|
||||
return this.recipeService.create(owner, spec);
|
||||
}
|
||||
|
||||
@ -146,7 +147,7 @@ public class RecipeControllerTests {
|
||||
.andExpect(jsonPath("$.recipe.owner.username").value(owner.getUsername()))
|
||||
.andExpect(jsonPath("$.recipe.starCount").value(0))
|
||||
.andExpect(jsonPath("$.recipe.viewerCount").value(0))
|
||||
.andExpect(jsonPath("$.recipe.isPublic").value(true))
|
||||
.andExpect(jsonPath("$.recipe.public").value(true))
|
||||
.andExpect(jsonPath("$.recipe.mainImage").value(nullValue()))
|
||||
.andExpect(jsonPath("$.isStarred").value(nullValue()))
|
||||
.andExpect(jsonPath("$.isOwner").value(nullValue()));
|
||||
@ -225,13 +226,14 @@ public class RecipeControllerTests {
|
||||
}
|
||||
|
||||
private String getUpdateBody() throws JsonProcessingException {
|
||||
final RecipeUpdateSpec spec = new RecipeUpdateSpec();
|
||||
spec.setTitle("Updated Test Recipe");
|
||||
spec.setPreparationTime(15);
|
||||
spec.setCookingTime(30);
|
||||
spec.setTotalTime(45);
|
||||
spec.setRawText("# Hello, Updated World!");
|
||||
spec.setIsPublic(true);
|
||||
final RecipeUpdateSpec spec = RecipeUpdateSpec.builder()
|
||||
.title("Updated Test Recipe")
|
||||
.preparationTime(15)
|
||||
.cookingTime(30)
|
||||
.totalTime(45)
|
||||
.rawText("# Hello, Updated World!")
|
||||
.isPublic(true)
|
||||
.build();
|
||||
return this.objectMapper.writeValueAsString(spec);
|
||||
}
|
||||
|
||||
@ -259,7 +261,7 @@ public class RecipeControllerTests {
|
||||
.andExpect(jsonPath("$.recipe.owner.username").value(owner.getUsername()))
|
||||
.andExpect(jsonPath("$.recipe.starCount").value(0))
|
||||
.andExpect(jsonPath("$.recipe.viewerCount").value(0))
|
||||
.andExpect(jsonPath("$.recipe.isPublic").value(true))
|
||||
.andExpect(jsonPath("$.recipe.public").value(true))
|
||||
.andExpect(jsonPath("$.recipe.mainImage").value(nullValue()))
|
||||
.andExpect(jsonPath("$.isStarred").value(false))
|
||||
.andExpect(jsonPath("$.isOwner").value(true));
|
||||
@ -271,21 +273,25 @@ public class RecipeControllerTests {
|
||||
|
||||
final Image hal9000 = this.createHal9000(owner);
|
||||
|
||||
final RecipeCreateSpec createSpec = new RecipeCreateSpec();
|
||||
createSpec.setTitle("Test Recipe");
|
||||
createSpec.setSlug("test-recipe");
|
||||
createSpec.setPublic(false);
|
||||
createSpec.setRawText("# Hello, World!");
|
||||
createSpec.setMainImage(hal9000);
|
||||
final RecipeCreateSpec createSpec = RecipeCreateSpec.builder()
|
||||
.title("Test Recipe")
|
||||
.slug(UUID.randomUUID().toString())
|
||||
.isPublic(false)
|
||||
.rawText("# Hello, World!")
|
||||
.mainImage(hal9000)
|
||||
.build();
|
||||
Recipe recipe = this.recipeService.create(owner, createSpec);
|
||||
|
||||
final RecipeUpdateSpec updateSpec = new RecipeUpdateSpec();
|
||||
updateSpec.setTitle("Updated Test Recipe");
|
||||
updateSpec.setRawText("# Hello, Updated World!");
|
||||
final RecipeUpdateSpec.MainImageUpdateSpec mainImageUpdateSpec = new RecipeUpdateSpec.MainImageUpdateSpec();
|
||||
mainImageUpdateSpec.setUsername(hal9000.getOwner().getUsername());
|
||||
mainImageUpdateSpec.setFilename(hal9000.getUserFilename());
|
||||
updateSpec.setMainImage(mainImageUpdateSpec);
|
||||
final RecipeUpdateSpec updateSpec = RecipeUpdateSpec.builder()
|
||||
.title("Updated Test Recipe")
|
||||
.rawText("# Hello, Updated World!")
|
||||
.mainImage(
|
||||
RecipeUpdateSpec.MainImageUpdateSpec.builder()
|
||||
.username(hal9000.getOwner().getUsername())
|
||||
.filename(hal9000.getUserFilename())
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
final String body = this.objectMapper.writeValueAsString(updateSpec);
|
||||
|
||||
final String accessToken = this.getAccessToken(owner);
|
||||
|
||||
@ -58,11 +58,12 @@ public class RecipeServiceTests {
|
||||
}
|
||||
|
||||
private Recipe createTestRecipe(@Nullable User owner, boolean isPublic) {
|
||||
final RecipeCreateSpec spec = new RecipeCreateSpec();
|
||||
spec.setSlug(UUID.randomUUID().toString());
|
||||
spec.setTitle("My Recipe");
|
||||
spec.setRawText("Hello!");
|
||||
spec.setPublic(isPublic);
|
||||
final RecipeCreateSpec spec = RecipeCreateSpec.builder()
|
||||
.slug(UUID.randomUUID().toString())
|
||||
.title("My Recipe")
|
||||
.rawText("Hello!")
|
||||
.isPublic(isPublic)
|
||||
.build();
|
||||
return this.recipeService.create(owner, spec);
|
||||
}
|
||||
|
||||
@ -80,7 +81,9 @@ public class RecipeServiceTests {
|
||||
|
||||
@Test
|
||||
public void createWithoutOwnerThrowsAccessDenied() {
|
||||
assertThrows(AccessDeniedException.class, () -> this.recipeService.create(null, new RecipeCreateSpec()));
|
||||
assertThrows(AccessDeniedException.class, () -> this.recipeService.create(
|
||||
null, RecipeCreateSpec.builder().build()
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -156,8 +159,9 @@ public class RecipeServiceTests {
|
||||
final User owner = this.seedUser();
|
||||
final User viewer = this.seedUser();
|
||||
final Recipe notYetPublicRecipe = this.createTestRecipe(owner);
|
||||
final RecipeUpdateSpec updateSpec = new RecipeUpdateSpec(notYetPublicRecipe);
|
||||
updateSpec.setIsPublic(true);
|
||||
final RecipeUpdateSpec updateSpec = RecipeUpdateSpec.fromRecipeToBuilder(notYetPublicRecipe)
|
||||
.isPublic(true)
|
||||
.build();
|
||||
final Recipe publicRecipe = this.recipeService.update(
|
||||
notYetPublicRecipe.getOwner().getUsername(),
|
||||
notYetPublicRecipe.getSlug(),
|
||||
@ -284,14 +288,16 @@ public class RecipeServiceTests {
|
||||
@Test
|
||||
public void updateRawText() throws RecipeException, ImageException {
|
||||
final User owner = this.seedUser();
|
||||
final RecipeCreateSpec createSpec = new RecipeCreateSpec();
|
||||
createSpec.setSlug("my-recipe");
|
||||
createSpec.setTitle("My Recipe");
|
||||
createSpec.setRawText("# A Heading");
|
||||
final RecipeCreateSpec createSpec = RecipeCreateSpec.builder()
|
||||
.slug(UUID.randomUUID().toString())
|
||||
.title("My Recipe")
|
||||
.rawText("# A Heading")
|
||||
.build();
|
||||
Recipe recipe = this.recipeService.create(owner, createSpec);
|
||||
final String newRawText = "# A Heading\n## A Subheading";
|
||||
final RecipeUpdateSpec updateSpec = new RecipeUpdateSpec(recipe);
|
||||
updateSpec.setRawText(newRawText);
|
||||
final RecipeUpdateSpec updateSpec = RecipeUpdateSpec.fromRecipeToBuilder(recipe)
|
||||
.rawText(newRawText)
|
||||
.build();
|
||||
recipe = this.recipeService.update(
|
||||
recipe.getOwner().getUsername(),
|
||||
recipe.getSlug(),
|
||||
@ -306,8 +312,9 @@ public class RecipeServiceTests {
|
||||
final User owner = this.seedUser();
|
||||
final User notOwner = this.seedUser();
|
||||
final Recipe recipe = this.createTestRecipe(owner);
|
||||
final RecipeUpdateSpec updateSpec = new RecipeUpdateSpec();
|
||||
updateSpec.setRawText("should fail");
|
||||
final RecipeUpdateSpec updateSpec = RecipeUpdateSpec.fromRecipeToBuilder(recipe)
|
||||
.rawText("should fail")
|
||||
.build();
|
||||
assertThrows(
|
||||
AccessDeniedException.class,
|
||||
() -> this.recipeService.update(
|
||||
|
||||
@ -56,7 +56,7 @@ public class RecipeStarRepositoryTests {
|
||||
final RecipeStar starDraft = new RecipeStar();
|
||||
final RecipeStarId starId = new RecipeStarId();
|
||||
starId.setRecipeId(recipe.getId());
|
||||
starId.getOwnerId(owner.getId());
|
||||
starId.setOwnerId(owner.getId());
|
||||
starDraft.setId(starId);
|
||||
this.recipeStarRepository.save(starDraft);
|
||||
|
||||
|
||||
@ -44,11 +44,12 @@ public class RecipeStarServiceTests {
|
||||
}
|
||||
|
||||
private Recipe seedRecipe(User owner) {
|
||||
final RecipeCreateSpec spec = new RecipeCreateSpec();
|
||||
spec.setSlug(UUID.randomUUID().toString());
|
||||
spec.setTitle("Test Recipe");
|
||||
spec.setRawText("My great recipe has five ingredients.");
|
||||
spec.setPublic(true);
|
||||
final RecipeCreateSpec spec = RecipeCreateSpec.builder()
|
||||
.slug(UUID.randomUUID().toString())
|
||||
.title("Test Recipe")
|
||||
.rawText("My great recipe has five ingredients.")
|
||||
.isPublic(true)
|
||||
.build();
|
||||
return this.recipeService.create(owner, spec);
|
||||
}
|
||||
|
||||
|
||||
@ -102,12 +102,13 @@ public class DevConfiguration {
|
||||
logger.info("Created mainImage {} for {}", mainImage, recipePath);
|
||||
}
|
||||
|
||||
final RecipeCreateSpec recipeCreateSpec = new RecipeCreateSpec();
|
||||
recipeCreateSpec.setSlug(frontMatter.slug);
|
||||
recipeCreateSpec.setTitle(frontMatter.title);
|
||||
recipeCreateSpec.setRawText(rawRecipeText);
|
||||
recipeCreateSpec.setPublic(frontMatter.isPublic);
|
||||
recipeCreateSpec.setMainImage(mainImage);
|
||||
final RecipeCreateSpec recipeCreateSpec = RecipeCreateSpec.builder()
|
||||
.slug(frontMatter.slug)
|
||||
.title(frontMatter.title)
|
||||
.rawText(rawRecipeText)
|
||||
.isPublic(frontMatter.isPublic)
|
||||
.mainImage(mainImage)
|
||||
.build();
|
||||
final Recipe recipe = this.recipeService.create(testUser, recipeCreateSpec);
|
||||
logger.info("Created recipe {}", recipe);
|
||||
}
|
||||
|
||||
@ -75,6 +75,7 @@ public final class Recipe {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "main_image_id")
|
||||
@Nullable
|
||||
private Image mainImage;
|
||||
|
||||
@OneToOne(mappedBy = "recipe", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
package app.mealsmadeeasy.api.recipe;
|
||||
|
||||
import app.mealsmadeeasy.api.image.ImageException;
|
||||
import app.mealsmadeeasy.api.recipe.body.RecipeAiSearchBody;
|
||||
import app.mealsmadeeasy.api.recipe.body.RecipeSearchBody;
|
||||
import app.mealsmadeeasy.api.recipe.body.RecipeUpdateBody;
|
||||
import app.mealsmadeeasy.api.recipe.comment.RecipeComment;
|
||||
import app.mealsmadeeasy.api.recipe.comment.RecipeCommentCreateBody;
|
||||
import app.mealsmadeeasy.api.recipe.comment.RecipeCommentService;
|
||||
import app.mealsmadeeasy.api.recipe.comment.RecipeCommentView;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeAiSearchSpec;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
||||
import app.mealsmadeeasy.api.recipe.star.RecipeStar;
|
||||
import app.mealsmadeeasy.api.recipe.star.RecipeStarService;
|
||||
@ -94,10 +95,11 @@ public class RecipeController {
|
||||
@PathVariable String username,
|
||||
@PathVariable String slug,
|
||||
@RequestParam(defaultValue = "true") boolean includeRawText,
|
||||
@RequestBody RecipeUpdateSpec updateSpec,
|
||||
@RequestBody RecipeUpdateBody updateBody,
|
||||
@AuthenticationPrincipal User principal
|
||||
) throws ImageException, RecipeException {
|
||||
final Recipe updated = this.recipeService.update(username, slug, updateSpec, principal);
|
||||
final RecipeUpdateSpec spec = RecipeUpdateSpec.from(updateBody);
|
||||
final Recipe updated = this.recipeService.update(username, slug, spec, principal);
|
||||
final FullRecipeView view = this.recipeService.toFullRecipeView(updated, includeRawText, principal);
|
||||
return ResponseEntity.ok(this.getFullViewWrapper(username, slug, view, principal));
|
||||
}
|
||||
@ -117,9 +119,9 @@ public class RecipeController {
|
||||
@AuthenticationPrincipal User user
|
||||
) {
|
||||
if (recipeSearchBody.getType() == RecipeSearchBody.Type.AI_PROMPT) {
|
||||
final RecipeAiSearchSpec spec = this.objectMapper.convertValue(
|
||||
final RecipeAiSearchBody spec = this.objectMapper.convertValue(
|
||||
recipeSearchBody.getData(),
|
||||
RecipeAiSearchSpec.class
|
||||
RecipeAiSearchBody.class
|
||||
);
|
||||
final List<RecipeInfoView> results = this.recipeService.aiSearch(spec, user);
|
||||
return ResponseEntity.ok(Map.of("results", results));
|
||||
|
||||
@ -10,7 +10,7 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface RecipeRepository extends JpaRepository<Recipe, Long> {
|
||||
public interface RecipeRepository extends JpaRepository<Recipe, Integer> {
|
||||
|
||||
List<Recipe> findAllByIsPublicIsTrue();
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface RecipeSecurity {
|
||||
boolean isOwner(Recipe recipe, User user);
|
||||
boolean isOwner(long recipeId, User user) throws RecipeException;
|
||||
boolean isOwner(Integer recipeId, User user) throws RecipeException;
|
||||
boolean isOwner(String username, String slug, @Nullable User user) throws RecipeException;
|
||||
boolean isViewableBy(Recipe recipe, @Nullable User user) throws RecipeException;
|
||||
boolean isViewableBy(String ownerUsername, String slug, @Nullable User user) throws RecipeException;
|
||||
boolean isViewableBy(long recipeId, @Nullable User user) throws RecipeException;
|
||||
boolean isViewableBy(Integer recipeId, @Nullable User user) throws RecipeException;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ public class RecipeSecurityImpl implements RecipeSecurity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOwner(long recipeId, User user) throws RecipeException {
|
||||
public boolean isOwner(Integer recipeId, User user) throws RecipeException {
|
||||
final Recipe recipe = this.recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_ID,
|
||||
"No such Recipe with id " + recipeId
|
||||
@ -78,7 +78,7 @@ public class RecipeSecurityImpl implements RecipeSecurity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewableBy(long recipeId, @Nullable User user) throws RecipeException {
|
||||
public boolean isViewableBy(Integer recipeId, @Nullable User user) throws RecipeException {
|
||||
final Recipe recipe = this.recipeRepository.findById(recipeId).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_ID,
|
||||
"No such Recipe with id: " + recipeId
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package app.mealsmadeeasy.api.recipe;
|
||||
|
||||
import app.mealsmadeeasy.api.image.ImageException;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeAiSearchSpec;
|
||||
import app.mealsmadeeasy.api.recipe.body.RecipeAiSearchBody;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeCreateSpec;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
||||
import app.mealsmadeeasy.api.recipe.view.FullRecipeView;
|
||||
@ -19,11 +19,11 @@ public interface RecipeService {
|
||||
|
||||
Recipe create(@Nullable User owner, RecipeCreateSpec spec);
|
||||
|
||||
Recipe getById(long id, @Nullable User viewer) throws RecipeException;
|
||||
Recipe getByIdWithStars(long id, @Nullable User viewer) throws RecipeException;
|
||||
Recipe getById(Integer id, @Nullable User viewer) throws RecipeException;
|
||||
Recipe getByIdWithStars(Integer id, @Nullable User viewer) throws RecipeException;
|
||||
Recipe getByUsernameAndSlug(String username, String slug, @Nullable User viewer) throws RecipeException;
|
||||
|
||||
FullRecipeView getFullViewById(long id, @Nullable User viewer) throws RecipeException;
|
||||
FullRecipeView getFullViewById(Integer id, @Nullable User viewer) throws RecipeException;
|
||||
FullRecipeView getFullViewByUsernameAndSlug(
|
||||
String username,
|
||||
String slug,
|
||||
@ -37,16 +37,16 @@ public interface RecipeService {
|
||||
List<Recipe> getRecipesViewableBy(User viewer);
|
||||
List<Recipe> getRecipesOwnedBy(User owner);
|
||||
|
||||
List<RecipeInfoView> aiSearch(RecipeAiSearchSpec searchSpec, @Nullable User viewer);
|
||||
List<RecipeInfoView> aiSearch(RecipeAiSearchBody searchSpec, @Nullable User viewer);
|
||||
|
||||
Recipe update(String username, String slug, RecipeUpdateSpec spec, User modifier)
|
||||
throws RecipeException, ImageException;
|
||||
|
||||
Recipe addViewer(long id, User modifier, User viewer) throws RecipeException;
|
||||
Recipe removeViewer(long id, User modifier, User viewer) throws RecipeException;
|
||||
Recipe clearAllViewers(long id, User modifier) throws RecipeException;
|
||||
Recipe addViewer(Integer id, User modifier, User viewer) throws RecipeException;
|
||||
Recipe removeViewer(Integer id, User modifier, User viewer) throws RecipeException;
|
||||
Recipe clearAllViewers(Integer id, User modifier) throws RecipeException;
|
||||
|
||||
void deleteRecipe(long id, User modifier);
|
||||
void deleteRecipe(Integer id, User modifier);
|
||||
|
||||
FullRecipeView toFullRecipeView(Recipe recipe, boolean includeRawText, @Nullable User viewer);
|
||||
RecipeInfoView toRecipeInfoView(Recipe recipe, @Nullable User viewer);
|
||||
|
||||
@ -5,7 +5,7 @@ import app.mealsmadeeasy.api.image.ImageException;
|
||||
import app.mealsmadeeasy.api.image.ImageService;
|
||||
import app.mealsmadeeasy.api.image.view.ImageView;
|
||||
import app.mealsmadeeasy.api.markdown.MarkdownService;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeAiSearchSpec;
|
||||
import app.mealsmadeeasy.api.recipe.body.RecipeAiSearchBody;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeCreateSpec;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeUpdateSpec;
|
||||
import app.mealsmadeeasy.api.recipe.star.RecipeStarRepository;
|
||||
@ -58,16 +58,16 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
}
|
||||
final Recipe draft = new Recipe();
|
||||
draft.setCreated(OffsetDateTime.now());
|
||||
draft.setOwner((User) owner);
|
||||
draft.setOwner(owner);
|
||||
draft.setSlug(spec.getSlug());
|
||||
draft.setTitle(spec.getTitle());
|
||||
draft.setRawText(spec.getRawText());
|
||||
draft.setMainImage((Image) spec.getMainImage());
|
||||
draft.setMainImage(spec.getMainImage());
|
||||
draft.setIsPublic(spec.isPublic());
|
||||
return this.recipeRepository.save(draft);
|
||||
}
|
||||
|
||||
private Recipe findRecipeEntity(long id) throws RecipeException {
|
||||
private Recipe findRecipeEntity(Integer id) throws RecipeException {
|
||||
return this.recipeRepository.findById(id).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_ID, "No such Recipe with id: " + id
|
||||
));
|
||||
@ -75,13 +75,13 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
|
||||
@Override
|
||||
@PostAuthorize("@recipeSecurity.isViewableBy(returnObject, #viewer)")
|
||||
public Recipe getById(long id, User viewer) throws RecipeException {
|
||||
public Recipe getById(Integer id, User viewer) throws RecipeException {
|
||||
return this.findRecipeEntity(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostAuthorize("@recipeSecurity.isViewableBy(returnObject, #viewer)")
|
||||
public Recipe getByIdWithStars(long id, @Nullable User viewer) throws RecipeException {
|
||||
public Recipe getByIdWithStars(Integer id, @Nullable User viewer) throws RecipeException {
|
||||
return this.recipeRepository.findByIdWithStars(id).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_ID,
|
||||
"No such Recipe with id: " + id
|
||||
@ -145,7 +145,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
|
||||
@Override
|
||||
@PreAuthorize("@recipeSecurity.isViewableBy(#id, #viewer)")
|
||||
public FullRecipeView getFullViewById(long id, @Nullable User viewer) throws RecipeException {
|
||||
public FullRecipeView getFullViewById(Integer id, @Nullable User viewer) throws RecipeException {
|
||||
final Recipe recipe = this.recipeRepository.findById(id).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_ID, "No such Recipe for id: " + id
|
||||
));
|
||||
@ -170,7 +170,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
|
||||
@Override
|
||||
public Slice<RecipeInfoView> getInfoViewsViewableBy(Pageable pageable, @Nullable User viewer) {
|
||||
return this.recipeRepository.findAllViewableBy((User) viewer, pageable).map(recipe ->
|
||||
return this.recipeRepository.findAllViewableBy(viewer, pageable).map(recipe ->
|
||||
this.getInfoView(recipe, viewer)
|
||||
);
|
||||
}
|
||||
@ -178,7 +178,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
@Override
|
||||
public List<Recipe> getByMinimumStars(long minimumStars, User viewer) {
|
||||
return List.copyOf(
|
||||
this.recipeRepository.findAllViewableByStarsGreaterThanEqual(minimumStars, (User) viewer)
|
||||
this.recipeRepository.findAllViewableByStarsGreaterThanEqual(minimumStars, viewer)
|
||||
);
|
||||
}
|
||||
|
||||
@ -189,16 +189,16 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
|
||||
@Override
|
||||
public List<Recipe> getRecipesViewableBy(User viewer) {
|
||||
return List.copyOf(this.recipeRepository.findAllByViewersContaining((User) viewer));
|
||||
return List.copyOf(this.recipeRepository.findAllByViewersContaining(viewer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Recipe> getRecipesOwnedBy(User owner) {
|
||||
return List.copyOf(this.recipeRepository.findAllByOwner((User) owner));
|
||||
return List.copyOf(this.recipeRepository.findAllByOwner(owner));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecipeInfoView> aiSearch(RecipeAiSearchSpec searchSpec, @Nullable User viewer) {
|
||||
public List<RecipeInfoView> aiSearch(RecipeAiSearchBody searchSpec, @Nullable User viewer) {
|
||||
final float[] queryEmbedding = this.embeddingModel.embed(searchSpec.getPrompt());
|
||||
final List<Recipe> results;
|
||||
if (viewer == null) {
|
||||
@ -211,6 +211,51 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
.toList();
|
||||
}
|
||||
|
||||
private void prepareForUpdate(RecipeUpdateSpec spec, Recipe recipe, User modifier) throws ImageException {
|
||||
boolean didUpdate = false;
|
||||
if (spec.getTitle() != null) {
|
||||
recipe.setTitle(spec.getTitle());
|
||||
didUpdate = true;
|
||||
}
|
||||
if (spec.getPreparationTime() != null) {
|
||||
recipe.setPreparationTime(spec.getPreparationTime());
|
||||
didUpdate = true;
|
||||
}
|
||||
if (spec.getCookingTime() != null) {
|
||||
recipe.setCookingTime(spec.getCookingTime());
|
||||
didUpdate = true;
|
||||
}
|
||||
if (spec.getTotalTime() != null) {
|
||||
recipe.setTotalTime(spec.getTotalTime());
|
||||
didUpdate = true;
|
||||
}
|
||||
|
||||
if (spec.getRawText() != null) {
|
||||
recipe.setRawText(spec.getRawText());
|
||||
recipe.setCachedRenderedText(null);
|
||||
didUpdate = true;
|
||||
}
|
||||
|
||||
if (spec.getIsPublic() != null) {
|
||||
recipe.setIsPublic(spec.getIsPublic());
|
||||
didUpdate = true;
|
||||
}
|
||||
|
||||
// TODO: we have to think about how to unset the main image vs. just leaving it out of the request
|
||||
if (spec.getMainImage() != null) {
|
||||
final Image mainImage = this.imageService.getByUsernameAndFilename(
|
||||
spec.getMainImage().getUsername(),
|
||||
spec.getMainImage().getFilename(),
|
||||
modifier
|
||||
);
|
||||
recipe.setMainImage(mainImage);
|
||||
}
|
||||
|
||||
if (didUpdate) {
|
||||
recipe.setModified(OffsetDateTime.now());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("@recipeSecurity.isOwner(#username, #slug, #modifier)")
|
||||
public Recipe update(String username, String slug, RecipeUpdateSpec spec, User modifier)
|
||||
@ -221,56 +266,35 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
"No such Recipe for username " + username + " and slug: " + slug
|
||||
)
|
||||
);
|
||||
|
||||
recipe.setTitle(spec.getTitle());
|
||||
recipe.setPreparationTime(spec.getPreparationTime());
|
||||
recipe.setCookingTime(spec.getCookingTime());
|
||||
recipe.setTotalTime(spec.getTotalTime());
|
||||
recipe.setRawText(spec.getRawText());
|
||||
recipe.setCachedRenderedText(null);
|
||||
recipe.setIsPublic(spec.getIsPublic());
|
||||
|
||||
final Image mainImage;
|
||||
if (spec.getMainImage() == null) {
|
||||
mainImage = null;
|
||||
} else {
|
||||
mainImage = (Image) this.imageService.getByUsernameAndFilename(
|
||||
spec.getMainImage().getUsername(),
|
||||
spec.getMainImage().getFilename(),
|
||||
modifier
|
||||
);
|
||||
}
|
||||
recipe.setMainImage(mainImage);
|
||||
|
||||
recipe.setModified(OffsetDateTime.now());
|
||||
this.prepareForUpdate(spec, recipe, modifier);
|
||||
return this.recipeRepository.save(recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("@recipeSecurity.isOwner(#id, #modifier)")
|
||||
public Recipe addViewer(long id, User modifier, User viewer) throws RecipeException {
|
||||
public Recipe addViewer(Integer id, User modifier, User viewer) throws RecipeException {
|
||||
final Recipe entity = this.recipeRepository.findByIdWithViewers(id).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_ID, "No such Recipe with id: " + id
|
||||
));
|
||||
final Set<User> viewers = new HashSet<>(entity.getViewers());
|
||||
viewers.add((User) viewer);
|
||||
viewers.add(viewer);
|
||||
entity.setViewers(viewers);
|
||||
return this.recipeRepository.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("@recipeSecurity.isOwner(#id, #modifier)")
|
||||
public Recipe removeViewer(long id, User modifier, User viewer) throws RecipeException {
|
||||
public Recipe removeViewer(Integer id, User modifier, User viewer) throws RecipeException {
|
||||
final Recipe entity = this.findRecipeEntity(id);
|
||||
final Set<User> viewers = new HashSet<>(entity.getViewers());
|
||||
viewers.remove((User) viewer);
|
||||
viewers.remove(viewer);
|
||||
entity.setViewers(viewers);
|
||||
return this.recipeRepository.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("@recipeSecurity.isOwner(#id, #modifier)")
|
||||
public Recipe clearAllViewers(long id, User modifier) throws RecipeException {
|
||||
public Recipe clearAllViewers(Integer id, User modifier) throws RecipeException {
|
||||
final Recipe entity = this.findRecipeEntity(id);
|
||||
entity.setViewers(new HashSet<>());
|
||||
return this.recipeRepository.save(entity);
|
||||
@ -278,18 +302,18 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
|
||||
@Override
|
||||
@PreAuthorize("@recipeSecurity.isOwner(#id, #modifier)")
|
||||
public void deleteRecipe(long id, User modifier) {
|
||||
public void deleteRecipe(Integer id, User modifier) {
|
||||
this.recipeRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullRecipeView toFullRecipeView(Recipe recipe, boolean includeRawText, @Nullable User viewer) {
|
||||
return this.getFullView((Recipe) recipe, includeRawText, viewer);
|
||||
return this.getFullView(recipe, includeRawText, viewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeInfoView toRecipeInfoView(Recipe recipe, @Nullable User viewer) {
|
||||
return this.getInfoView((Recipe) recipe, viewer);
|
||||
return this.getInfoView(recipe, viewer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
package app.mealsmadeeasy.api.recipe.body;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RecipeAiSearchBody {
|
||||
private String prompt;
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
package app.mealsmadeeasy.api.recipe.body;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class RecipeSearchBody {
|
||||
|
||||
public enum Type {
|
||||
@ -11,20 +14,4 @@ public class RecipeSearchBody {
|
||||
private Type type;
|
||||
private Map<String, Object> data;
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Map<String, Object> getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public void setData(Map<String, Object> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package app.mealsmadeeasy.api.recipe.body;
|
||||
|
||||
import lombok.Data;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Data
|
||||
public class RecipeUpdateBody {
|
||||
|
||||
@Data
|
||||
public static class MainImageUpdateBody {
|
||||
private String username;
|
||||
private String filename;
|
||||
}
|
||||
|
||||
private @Nullable String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
private @Nullable Integer cookingTime;
|
||||
private @Nullable Integer totalTime;
|
||||
private @Nullable String rawText;
|
||||
private @Nullable Boolean isPublic;
|
||||
private @Nullable MainImageUpdateBody mainImage;
|
||||
|
||||
}
|
||||
@ -8,6 +8,7 @@ import lombok.Data;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "recipe_comment")
|
||||
@Data
|
||||
public final class RecipeComment {
|
||||
|
||||
|
||||
@ -1,15 +1,8 @@
|
||||
package app.mealsmadeeasy.api.recipe.comment;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RecipeCommentCreateBody {
|
||||
|
||||
private String text;
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface RecipeCommentRepository extends JpaRepository<RecipeComment, Long> {
|
||||
public interface RecipeCommentRepository extends JpaRepository<RecipeComment, Integer> {
|
||||
void deleteAllByRecipe(Recipe recipe);
|
||||
Slice<RecipeComment> findAllByRecipe(Recipe recipe, Pageable pageable);
|
||||
}
|
||||
|
||||
@ -8,9 +8,9 @@ import org.springframework.data.domain.Slice;
|
||||
public interface RecipeCommentService {
|
||||
RecipeComment create(String recipeUsername, String recipeSlug, User owner, RecipeCommentCreateBody body)
|
||||
throws RecipeException;
|
||||
RecipeComment get(long commentId, User viewer) throws RecipeException;
|
||||
RecipeComment get(Integer commentId, User viewer) throws RecipeException;
|
||||
Slice<RecipeCommentView> getComments(String recipeUsername, String recipeSlug, Pageable pageable, User viewer)
|
||||
throws RecipeException;
|
||||
RecipeComment update(long commentId, User viewer, RecipeCommentUpdateSpec spec) throws RecipeException;
|
||||
void delete(long commentId, User modifier) throws RecipeException;
|
||||
RecipeComment update(Integer commentId, User viewer, RecipeCommentUpdateSpec spec) throws RecipeException;
|
||||
void delete(Integer commentId, User modifier) throws RecipeException;
|
||||
}
|
||||
|
||||
@ -56,14 +56,14 @@ public class RecipeCommentServiceImpl implements RecipeCommentService {
|
||||
}
|
||||
|
||||
@PostAuthorize("@recipeSecurity.isViewableBy(returnObject.recipe, #viewer)")
|
||||
private RecipeComment loadCommentEntity(long commentId, User viewer) throws RecipeException {
|
||||
private RecipeComment loadCommentEntity(Integer commentId, User viewer) throws RecipeException {
|
||||
return this.recipeCommentRepository.findById(commentId).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_COMMENT_ID, "No such RecipeComment for id: " + commentId
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeComment get(long commentId, User viewer) throws RecipeException {
|
||||
public RecipeComment get(Integer commentId, User viewer) throws RecipeException {
|
||||
return this.loadCommentEntity(commentId, viewer);
|
||||
}
|
||||
|
||||
@ -84,21 +84,21 @@ public class RecipeCommentServiceImpl implements RecipeCommentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeComment update(long commentId, User viewer, RecipeCommentUpdateSpec spec) throws RecipeException {
|
||||
public RecipeComment update(Integer commentId, User viewer, RecipeCommentUpdateSpec spec) throws RecipeException {
|
||||
final RecipeComment entity = this.loadCommentEntity(commentId, viewer);
|
||||
entity.setRawText(spec.getRawText());
|
||||
return this.recipeCommentRepository.save(entity);
|
||||
}
|
||||
|
||||
@PostAuthorize("@recipeSecurity.isOwner(returnObject.recipe, #modifier)")
|
||||
private RecipeComment loadForDelete(long commentId, User modifier) throws RecipeException {
|
||||
private RecipeComment loadForDelete(Integer commentId, User modifier) throws RecipeException {
|
||||
return this.recipeCommentRepository.findById(commentId).orElseThrow(() -> new RecipeException(
|
||||
RecipeException.Type.INVALID_COMMENT_ID, "No such RecipeComment for id: " + commentId
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(long commentId, User modifier) throws RecipeException {
|
||||
public void delete(Integer commentId, User modifier) throws RecipeException {
|
||||
final RecipeComment entityToDelete = this.loadForDelete(commentId, modifier);
|
||||
this.recipeCommentRepository.delete(entityToDelete);
|
||||
}
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
package app.mealsmadeeasy.api.recipe.comment;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public class RecipeCommentUpdateSpec {
|
||||
|
||||
private String rawText;
|
||||
|
||||
public String getRawText() {
|
||||
return this.rawText;
|
||||
}
|
||||
|
||||
public void setRawText(String rawText) {
|
||||
this.rawText = rawText;
|
||||
}
|
||||
|
||||
String rawText;
|
||||
}
|
||||
|
||||
@ -1,88 +1,36 @@
|
||||
package app.mealsmadeeasy.api.recipe.comment;
|
||||
|
||||
import app.mealsmadeeasy.api.user.view.UserInfoView;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public class RecipeCommentView {
|
||||
|
||||
public static RecipeCommentView from(RecipeComment comment, boolean includeRawText) {
|
||||
final RecipeCommentView view = new RecipeCommentView();
|
||||
view.setId(comment.getId());
|
||||
view.setCreated(comment.getCreated());
|
||||
view.setModified(comment.getModified());
|
||||
view.setText(((RecipeComment) comment).getCachedRenderedText());
|
||||
final var builder = RecipeCommentView.builder()
|
||||
.id(comment.getId())
|
||||
.created(comment.getCreated())
|
||||
.modified(comment.getModified())
|
||||
.text(comment.getCachedRenderedText())
|
||||
.owner(UserInfoView.from(comment.getOwner()))
|
||||
.recipeId(comment.getRecipe().getId());
|
||||
if (includeRawText) {
|
||||
view.setRawText(comment.getRawText());
|
||||
builder.rawText(comment.getRawText());
|
||||
}
|
||||
view.setOwner(UserInfoView.from(comment.getOwner()));
|
||||
view.setRecipeId(comment.getRecipe().getId());
|
||||
return view;
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private Integer id;
|
||||
private OffsetDateTime created;
|
||||
private @Nullable OffsetDateTime modified;
|
||||
private String text;
|
||||
private @Nullable String rawText;
|
||||
private UserInfoView owner;
|
||||
private Integer recipeId;
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(@Nullable OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public @Nullable String getRawText() {
|
||||
return this.rawText;
|
||||
}
|
||||
|
||||
public void setRawText(@Nullable String rawText) {
|
||||
this.rawText = rawText;
|
||||
}
|
||||
|
||||
public UserInfoView getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(UserInfoView owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Integer getRecipeId() {
|
||||
return this.recipeId;
|
||||
}
|
||||
|
||||
public void setRecipeId(Integer recipeId) {
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
Integer id;
|
||||
OffsetDateTime created;
|
||||
@Nullable OffsetDateTime modified;
|
||||
String text;
|
||||
@Nullable String rawText;
|
||||
UserInfoView owner;
|
||||
Integer recipeId;
|
||||
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
package app.mealsmadeeasy.api.recipe.spec;
|
||||
|
||||
public class RecipeAiSearchSpec {
|
||||
|
||||
private String prompt;
|
||||
|
||||
public String getPrompt() {
|
||||
return this.prompt;
|
||||
}
|
||||
|
||||
public void setPrompt(String prompt) {
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,81 +1,19 @@
|
||||
package app.mealsmadeeasy.api.recipe.spec;
|
||||
|
||||
import app.mealsmadeeasy.api.image.Image;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public class RecipeCreateSpec {
|
||||
|
||||
private String slug;
|
||||
private String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
private @Nullable Integer cookingTime;
|
||||
private @Nullable Integer totalTime;
|
||||
private String rawText;
|
||||
private boolean isPublic;
|
||||
private @Nullable Image mainImage;
|
||||
|
||||
public String getSlug() {
|
||||
return this.slug;
|
||||
}
|
||||
|
||||
public void setSlug(String slug) {
|
||||
this.slug = slug;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public @Nullable Integer getPreparationTime() {
|
||||
return this.preparationTime;
|
||||
}
|
||||
|
||||
public void setPreparationTime(@Nullable Integer preparationTime) {
|
||||
this.preparationTime = preparationTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getCookingTime() {
|
||||
return this.cookingTime;
|
||||
}
|
||||
|
||||
public void setCookingTime(@Nullable Integer cookingTime) {
|
||||
this.cookingTime = cookingTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getTotalTime() {
|
||||
return this.totalTime;
|
||||
}
|
||||
|
||||
public void setTotalTime(@Nullable Integer totalTime) {
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public String getRawText() {
|
||||
return this.rawText;
|
||||
}
|
||||
|
||||
public void setRawText(String rawText) {
|
||||
this.rawText = rawText;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return this.isPublic;
|
||||
}
|
||||
|
||||
public void setPublic(boolean isPublic) {
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
public @Nullable Image getMainImage() {
|
||||
return this.mainImage;
|
||||
}
|
||||
|
||||
public void setMainImage(@Nullable Image mainImage) {
|
||||
this.mainImage = mainImage;
|
||||
}
|
||||
|
||||
String slug;
|
||||
String title;
|
||||
@Nullable Integer preparationTime;
|
||||
@Nullable Integer cookingTime;
|
||||
@Nullable Integer totalTime;
|
||||
String rawText;
|
||||
boolean isPublic;
|
||||
@Nullable Image mainImage;
|
||||
}
|
||||
|
||||
@ -2,120 +2,73 @@ package app.mealsmadeeasy.api.recipe.spec;
|
||||
|
||||
import app.mealsmadeeasy.api.image.Image;
|
||||
import app.mealsmadeeasy.api.recipe.Recipe;
|
||||
import app.mealsmadeeasy.api.recipe.body.RecipeUpdateBody;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
// For now, we cannot change slug after creation.
|
||||
// In the future, we may be able to have redirects from
|
||||
// old slugs to new slugs.
|
||||
@Value
|
||||
@Builder
|
||||
public class RecipeUpdateSpec {
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public static class MainImageUpdateSpec {
|
||||
|
||||
private String username;
|
||||
private String filename;
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
String username;
|
||||
String filename;
|
||||
}
|
||||
|
||||
private String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
private @Nullable Integer cookingTime;
|
||||
private @Nullable Integer totalTime;
|
||||
private String rawText;
|
||||
private boolean isPublic;
|
||||
private @Nullable MainImageUpdateSpec mainImage;
|
||||
|
||||
public RecipeUpdateSpec() {}
|
||||
|
||||
/**
|
||||
* Convenience constructor for testing purposes.
|
||||
*
|
||||
* @param recipe the Recipe to copy from
|
||||
*/
|
||||
public RecipeUpdateSpec(Recipe recipe) {
|
||||
this.title = recipe.getTitle();
|
||||
this.preparationTime = recipe.getPreparationTime();
|
||||
this.cookingTime = recipe.getCookingTime();
|
||||
this.totalTime = recipe.getTotalTime();
|
||||
this.rawText = recipe.getRawText();
|
||||
this.isPublic = recipe.getIsPublic();
|
||||
final @Nullable Image mainImage = recipe.getMainImage();
|
||||
public static RecipeUpdateSpec from(RecipeUpdateBody body) {
|
||||
final var b = RecipeUpdateSpec.builder()
|
||||
.title(body.getTitle())
|
||||
.preparationTime(body.getPreparationTime())
|
||||
.cookingTime(body.getCookingTime())
|
||||
.totalTime(body.getTotalTime())
|
||||
.rawText(body.getRawText())
|
||||
.isPublic(body.getIsPublic());
|
||||
final @Nullable RecipeUpdateBody.MainImageUpdateBody mainImage = body.getMainImage();
|
||||
if (mainImage != null) {
|
||||
this.mainImage = new MainImageUpdateSpec();
|
||||
this.mainImage.setUsername(mainImage.getOwner().getUsername());
|
||||
this.mainImage.setFilename(mainImage.getUserFilename());
|
||||
b.mainImage(
|
||||
MainImageUpdateSpec.builder()
|
||||
.username(mainImage.getUsername())
|
||||
.filename(mainImage.getFilename())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
return b.build();
|
||||
}
|
||||
|
||||
public @Nullable String getTitle() {
|
||||
return this.title;
|
||||
// For testing convenience only.
|
||||
@ApiStatus.Internal
|
||||
public static RecipeUpdateSpec.RecipeUpdateSpecBuilder fromRecipeToBuilder(Recipe recipe) {
|
||||
final var b = RecipeUpdateSpec.builder()
|
||||
.title(recipe.getTitle())
|
||||
.preparationTime(recipe.getPreparationTime())
|
||||
.cookingTime(recipe.getCookingTime())
|
||||
.totalTime(recipe.getTotalTime())
|
||||
.rawText(recipe.getRawText())
|
||||
.isPublic(recipe.getIsPublic());
|
||||
final @Nullable Image mainImage = recipe.getMainImage();
|
||||
if (recipe.getMainImage() != null) {
|
||||
b.mainImage(MainImageUpdateSpec.builder()
|
||||
.username(mainImage.getOwner().getUsername())
|
||||
.filename(mainImage.getUserFilename())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public void setTitle(@Nullable String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public @Nullable Integer getPreparationTime() {
|
||||
return this.preparationTime;
|
||||
}
|
||||
|
||||
public void setPreparationTime(@Nullable Integer preparationTime) {
|
||||
this.preparationTime = preparationTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getCookingTime() {
|
||||
return this.cookingTime;
|
||||
}
|
||||
|
||||
public void setCookingTime(@Nullable Integer cookingTime) {
|
||||
this.cookingTime = cookingTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getTotalTime() {
|
||||
return this.totalTime;
|
||||
}
|
||||
|
||||
public void setTotalTime(@Nullable Integer totalTime) {
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public @Nullable String getRawText() {
|
||||
return this.rawText;
|
||||
}
|
||||
|
||||
public void setRawText(@Nullable String rawText) {
|
||||
this.rawText = rawText;
|
||||
}
|
||||
|
||||
public boolean getIsPublic() {
|
||||
return this.isPublic;
|
||||
}
|
||||
|
||||
public void setIsPublic(boolean isPublic) {
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
public @Nullable MainImageUpdateSpec getMainImage() {
|
||||
return this.mainImage;
|
||||
}
|
||||
|
||||
public void setMainImage(@Nullable MainImageUpdateSpec mainImage) {
|
||||
this.mainImage = mainImage;
|
||||
}
|
||||
String title;
|
||||
@Nullable Integer preparationTime;
|
||||
@Nullable Integer cookingTime;
|
||||
@Nullable Integer totalTime;
|
||||
String rawText;
|
||||
Boolean isPublic;
|
||||
@Nullable MainImageUpdateSpec mainImage;
|
||||
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import lombok.Data;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Entity(name = "RecipeStar")
|
||||
@Entity
|
||||
@Table(name = "recipe_star")
|
||||
@Data
|
||||
public final class RecipeStar {
|
||||
|
||||
@ -2,10 +2,10 @@ package app.mealsmadeeasy.api.recipe.star;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
|
||||
import java.util.Objects;
|
||||
import lombok.Data;
|
||||
|
||||
@Embeddable
|
||||
@Data
|
||||
public class RecipeStarId {
|
||||
|
||||
@Column(name = "owner_id", nullable = false)
|
||||
@ -14,39 +14,4 @@ public class RecipeStarId {
|
||||
@Column(name = "recipe_id", nullable = false)
|
||||
private Integer recipeId;
|
||||
|
||||
public Integer getOwnerId() {
|
||||
return this.ownerId;
|
||||
}
|
||||
|
||||
public void getOwnerId(Integer ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public Integer getRecipeId() {
|
||||
return this.recipeId;
|
||||
}
|
||||
|
||||
public void setRecipeId(Integer recipeId) {
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof RecipeStarId other) {
|
||||
return this.recipeId.equals(other.recipeId) && this.ownerId.equals(other.ownerId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.recipeId, this.ownerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecipeStarId(" + this.recipeId + ", " + this.ownerId + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public class RecipeStarServiceImpl implements RecipeStarService {
|
||||
final RecipeStar draft = new RecipeStar();
|
||||
final RecipeStarId id = new RecipeStarId();
|
||||
id.setRecipeId(recipeId);
|
||||
id.getOwnerId(ownerId);
|
||||
id.setOwnerId(ownerId);
|
||||
draft.setId(id);
|
||||
draft.setTimestamp(OffsetDateTime.now());
|
||||
return this.recipeStarRepository.save(draft);
|
||||
|
||||
@ -4,11 +4,14 @@ import app.mealsmadeeasy.api.image.view.ImageView;
|
||||
import app.mealsmadeeasy.api.recipe.Recipe;
|
||||
import app.mealsmadeeasy.api.user.view.UserInfoView;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public class FullRecipeView {
|
||||
|
||||
public static FullRecipeView from(
|
||||
@ -19,162 +22,46 @@ public class FullRecipeView {
|
||||
int viewerCount,
|
||||
@Nullable ImageView mainImage
|
||||
) {
|
||||
final FullRecipeView view = new FullRecipeView();
|
||||
view.setId(recipe.getId());
|
||||
view.setCreated(recipe.getCreated());
|
||||
view.setModified(recipe.getModified());
|
||||
view.setSlug(recipe.getSlug());
|
||||
view.setTitle(recipe.getTitle());
|
||||
view.setPreparationTime(recipe.getPreparationTime());
|
||||
view.setCookingTime(recipe.getCookingTime());
|
||||
view.setTotalTime(recipe.getTotalTime());
|
||||
view.setText(renderedText);
|
||||
final var b = FullRecipeView.builder()
|
||||
.id(recipe.getId())
|
||||
.created(recipe.getCreated())
|
||||
.modified(recipe.getModified())
|
||||
.slug(recipe.getSlug())
|
||||
.title(recipe.getTitle())
|
||||
.preparationTime(recipe.getPreparationTime())
|
||||
.cookingTime(recipe.getCookingTime())
|
||||
.totalTime(recipe.getTotalTime())
|
||||
.text(renderedText)
|
||||
.owner(UserInfoView.from(recipe.getOwner()))
|
||||
.starCount(starCount)
|
||||
.viewerCount(viewerCount)
|
||||
.mainImage(mainImage)
|
||||
.isPublic(recipe.getIsPublic());
|
||||
if (includeRawText) {
|
||||
view.setRawText(recipe.getRawText());
|
||||
b.rawText(recipe.getRawText());
|
||||
}
|
||||
view.setOwner(UserInfoView.from(recipe.getOwner()));
|
||||
view.setStarCount(starCount);
|
||||
view.setViewerCount(viewerCount);
|
||||
view.setMainImage(mainImage);
|
||||
view.setIsPublic(recipe.getIsPublic());
|
||||
return view;
|
||||
return b.build();
|
||||
}
|
||||
|
||||
private long id;
|
||||
private OffsetDateTime created;
|
||||
private @Nullable OffsetDateTime modified;
|
||||
private String slug;
|
||||
private String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
private @Nullable Integer cookingTime;
|
||||
private @Nullable Integer totalTime;
|
||||
private String text;
|
||||
private @Nullable String rawText;
|
||||
private UserInfoView owner;
|
||||
private int starCount;
|
||||
private int viewerCount;
|
||||
private @Nullable ImageView mainImage;
|
||||
private boolean isPublic;
|
||||
Integer id;
|
||||
OffsetDateTime created;
|
||||
@Nullable OffsetDateTime modified;
|
||||
String slug;
|
||||
String title;
|
||||
@Nullable Integer preparationTime;
|
||||
@Nullable Integer cookingTime;
|
||||
@Nullable Integer totalTime;
|
||||
String text;
|
||||
@Nullable String rawText;
|
||||
UserInfoView owner;
|
||||
int starCount;
|
||||
int viewerCount;
|
||||
@Nullable ImageView mainImage;
|
||||
boolean isPublic;
|
||||
|
||||
public long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(@Nullable OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return this.slug;
|
||||
}
|
||||
|
||||
public void setSlug(String slug) {
|
||||
this.slug = slug;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public @Nullable Integer getPreparationTime() {
|
||||
return this.preparationTime;
|
||||
}
|
||||
|
||||
public void setPreparationTime(@Nullable Integer preparationTime) {
|
||||
this.preparationTime = preparationTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getCookingTime() {
|
||||
return this.cookingTime;
|
||||
}
|
||||
|
||||
public void setCookingTime(@Nullable Integer cookingTime) {
|
||||
this.cookingTime = cookingTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getTotalTime() {
|
||||
return this.totalTime;
|
||||
}
|
||||
|
||||
public void setTotalTime(@Nullable Integer totalTime) {
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public @Nullable String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public @Nullable String getRawText() {
|
||||
return this.rawText;
|
||||
}
|
||||
|
||||
public void setRawText(@Nullable String rawText) {
|
||||
this.rawText = rawText;
|
||||
}
|
||||
|
||||
public UserInfoView getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(UserInfoView owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public int getStarCount() {
|
||||
return this.starCount;
|
||||
}
|
||||
|
||||
public void setStarCount(int starCount) {
|
||||
this.starCount = starCount;
|
||||
}
|
||||
|
||||
public int getViewerCount() {
|
||||
return this.viewerCount;
|
||||
}
|
||||
|
||||
public void setViewerCount(int viewerCount) {
|
||||
this.viewerCount = viewerCount;
|
||||
}
|
||||
|
||||
public @Nullable ImageView getMainImage() {
|
||||
return this.mainImage;
|
||||
}
|
||||
|
||||
public void setMainImage(@Nullable ImageView mainImage) {
|
||||
this.mainImage = mainImage;
|
||||
}
|
||||
|
||||
public boolean getIsPublic() {
|
||||
return this.isPublic;
|
||||
}
|
||||
|
||||
public void setIsPublic(boolean isPublic) {
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package app.mealsmadeeasy.api.recipe.view;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public final class RecipeExceptionView {
|
||||
|
||||
private final String type;
|
||||
@ -10,12 +13,4 @@ public final class RecipeExceptionView {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,42 +3,44 @@ package app.mealsmadeeasy.api.recipe.view;
|
||||
import app.mealsmadeeasy.api.image.view.ImageView;
|
||||
import app.mealsmadeeasy.api.recipe.Recipe;
|
||||
import app.mealsmadeeasy.api.user.view.UserInfoView;
|
||||
import lombok.Data;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Data
|
||||
@Value
|
||||
@Builder
|
||||
public class RecipeInfoView {
|
||||
|
||||
public static RecipeInfoView from(Recipe recipe, int starCount, @Nullable ImageView mainImage) {
|
||||
final RecipeInfoView view = new RecipeInfoView();
|
||||
view.setId(recipe.getId());
|
||||
view.setCreated(recipe.getCreated());
|
||||
view.setModified(recipe.getModified());
|
||||
view.setSlug(recipe.getSlug());
|
||||
view.setTitle(recipe.getTitle());
|
||||
view.setPreparationTime(recipe.getPreparationTime());
|
||||
view.setCookingTime(recipe.getCookingTime());
|
||||
view.setTotalTime(recipe.getTotalTime());
|
||||
view.setOwner(UserInfoView.from(recipe.getOwner()));
|
||||
view.setPublic(recipe.getIsPublic());
|
||||
view.setStarCount(starCount);
|
||||
view.setMainImage(mainImage);
|
||||
return view;
|
||||
return RecipeInfoView.builder()
|
||||
.id(recipe.getId())
|
||||
.created(recipe.getCreated())
|
||||
.modified(recipe.getModified())
|
||||
.slug(recipe.getSlug())
|
||||
.title(recipe.getTitle())
|
||||
.preparationTime(recipe.getPreparationTime())
|
||||
.cookingTime(recipe.getCookingTime())
|
||||
.totalTime(recipe.getTotalTime())
|
||||
.owner(UserInfoView.from(recipe.getOwner()))
|
||||
.isPublic(recipe.getIsPublic())
|
||||
.starCount(starCount)
|
||||
.mainImage(mainImage)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Integer id;
|
||||
private OffsetDateTime created;
|
||||
private OffsetDateTime modified;
|
||||
private String slug;
|
||||
private String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
private @Nullable Integer cookingTime;
|
||||
private @Nullable Integer totalTime;
|
||||
private UserInfoView owner;
|
||||
private boolean isPublic;
|
||||
private int starCount;
|
||||
private @Nullable ImageView mainImage;
|
||||
Integer id;
|
||||
OffsetDateTime created;
|
||||
OffsetDateTime modified;
|
||||
String slug;
|
||||
String title;
|
||||
@Nullable Integer preparationTime;
|
||||
@Nullable Integer cookingTime;
|
||||
@Nullable Integer totalTime;
|
||||
UserInfoView owner;
|
||||
boolean isPublic;
|
||||
int starCount;
|
||||
@Nullable ImageView mainImage;
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user