Get recipe info views from RecipeService and RecipeController.

This commit is contained in:
JesseBrault0709 2024-07-09 17:46:17 +02:00
parent 4779070142
commit 1137f390b7
7 changed files with 151 additions and 4 deletions

View File

@ -7,8 +7,10 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -39,11 +41,12 @@ public class RecipeControllerTests {
}
@Test
public void getByIdPublicRecipeNoPrincipal() throws Exception {
@DirtiesContext
public void getRecipePageViewByIdPublicRecipeNoPrincipal() throws Exception {
final User owner = this.createTestUser("owner");
final Recipe recipe = this.createTestRecipe(owner);
this.recipeService.setPublic(recipe, owner, true);
this.mockMvc.perform(get("/recipe/{id}", recipe.getId()))
this.mockMvc.perform(get("/recipes/{id}", recipe.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(1))
.andExpect(jsonPath("$.title").value("Test Recipe"))
@ -54,4 +57,25 @@ public class RecipeControllerTests {
.andExpect(jsonPath("$.viewerCount").value(0));
}
@Test
@DirtiesContext
public void getRecipeInfoViewsNoPrincipal() throws Exception {
final User owner = this.createTestUser("owner");
final Recipe recipe = this.createTestRecipe(owner);
this.recipeService.setPublic(recipe, owner, true);
this.mockMvc.perform(get("/recipes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.slice.number").value(0))
.andExpect(jsonPath("$.slice.size").value(20))
.andExpect(jsonPath("$.content").isArray())
.andExpect(jsonPath("$.content", hasSize(1)))
.andExpect(jsonPath("$.content[0].id").value(recipe.getId()))
.andExpect(jsonPath("$.content[0].updated").exists())
.andExpect(jsonPath("$.content[0].title").value(recipe.getTitle()))
.andExpect(jsonPath("$.content[0].ownerId").value(owner.getId()))
.andExpect(jsonPath("$.content[0].ownerUsername").value(owner.getUsername()))
.andExpect(jsonPath("$.content[0].public").value(true))
.andExpect(jsonPath("$.content[0].starCount").value(0));
}
}

View File

@ -1,14 +1,20 @@
package app.mealsmadeeasy.api.recipe;
import app.mealsmadeeasy.api.recipe.view.RecipeExceptionView;
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
import app.mealsmadeeasy.api.recipe.view.RecipePageView;
import app.mealsmadeeasy.api.user.User;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/recipe")
@RequestMapping("/recipes")
public class RecipeController {
private final RecipeService recipeService;
@ -31,4 +37,19 @@ public class RecipeController {
return ResponseEntity.ok(this.recipeService.getPageViewById(id, user));
}
@GetMapping
public ResponseEntity<Map<String, Object>> getRecipeInfoViews(
Pageable pageable,
@AuthenticationPrincipal User user
) {
final Slice<RecipeInfoView> slice = this.recipeService.getInfoViewsViewableBy(pageable, user);
final Map<String, Object> view = new HashMap<>();
view.put("content", slice.getContent());
final Map<String, Object> sliceInfo = new HashMap<>();
sliceInfo.put("size", slice.getSize());
sliceInfo.put("number", slice.getNumber());
view.put("slice", sliceInfo);
return ResponseEntity.ok(view);
}
}

View File

@ -1,6 +1,8 @@
package app.mealsmadeeasy.api.recipe;
import app.mealsmadeeasy.api.user.UserEntity;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
@ -34,4 +36,7 @@ public interface RecipeRepository extends JpaRepository<RecipeEntity, Long> {
@Query("SELECT size(r.viewers) FROM Recipe r WHERE r.id = ?1")
int getViewerCount(long recipeId);
@Query("SELECT r FROM Recipe r WHERE r.isPublic OR ?1 MEMBER OF r.viewers")
Slice<RecipeEntity> findAllViewableBy(UserEntity viewer, Pageable pageable);
}

View File

@ -2,9 +2,12 @@ package app.mealsmadeeasy.api.recipe;
import app.mealsmadeeasy.api.recipe.comment.RecipeComment;
import app.mealsmadeeasy.api.recipe.star.RecipeStar;
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
import app.mealsmadeeasy.api.recipe.view.RecipePageView;
import app.mealsmadeeasy.api.user.User;
import org.jetbrains.annotations.Nullable;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import java.util.List;
@ -20,6 +23,7 @@ public interface RecipeService {
Recipe getByIdWithStars(long id, User viewer) throws RecipeException;
RecipePageView getPageViewById(long id, @Nullable User viewer) throws RecipeException;
Slice<RecipeInfoView> getInfoViewsViewableBy(Pageable pageable, @Nullable User viewer);
List<Recipe> getByMinimumStars(long minimumStars);
List<Recipe> getByMinimumStars(long minimumStars, User viewer);

View File

@ -6,6 +6,7 @@ import app.mealsmadeeasy.api.recipe.comment.RecipeCommentRepository;
import app.mealsmadeeasy.api.recipe.star.RecipeStar;
import app.mealsmadeeasy.api.recipe.star.RecipeStarEntity;
import app.mealsmadeeasy.api.recipe.star.RecipeStarRepository;
import app.mealsmadeeasy.api.recipe.view.RecipeInfoView;
import app.mealsmadeeasy.api.recipe.view.RecipePageView;
import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserEntity;
@ -15,6 +16,8 @@ import org.commonmark.renderer.html.HtmlRenderer;
import org.jetbrains.annotations.Nullable;
import org.jsoup.Jsoup;
import org.jsoup.safety.Safelist;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@ -127,6 +130,25 @@ public class RecipeServiceImpl implements RecipeService {
return view;
}
@Override
public Slice<RecipeInfoView> getInfoViewsViewableBy(Pageable pageable, @Nullable User viewer) {
return this.recipeRepository.findAllViewableBy((UserEntity) viewer, pageable).map(entity -> {
final RecipeInfoView view = new RecipeInfoView();
view.setId(entity.getId());
if (entity.getModified() != null) {
view.setUpdated(entity.getModified());
} else {
view.setUpdated(entity.getCreated());
}
view.setTitle(entity.getTitle());
view.setOwnerId(entity.getOwner().getId());
view.setOwnerUsername(entity.getOwner().getUsername());
view.setPublic(entity.isPublic());
view.setStarCount(this.getStarCount(entity, viewer));
return view;
});
}
@Override
public List<Recipe> getByMinimumStars(long minimumStars) {
return List.copyOf(this.recipeRepository.findAllPublicByStarsGreaterThanEqual(minimumStars));

View File

@ -0,0 +1,71 @@
package app.mealsmadeeasy.api.recipe.view;
import java.time.LocalDateTime;
public final class RecipeInfoView {
private long id;
private LocalDateTime updated;
private String title;
private long ownerId;
private String ownerUsername;
private boolean isPublic;
private int starCount;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public LocalDateTime getUpdated() {
return this.updated;
}
public void setUpdated(LocalDateTime updated) {
this.updated = updated;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public long getOwnerId() {
return this.ownerId;
}
public void setOwnerId(long ownerId) {
this.ownerId = ownerId;
}
public String getOwnerUsername() {
return this.ownerUsername;
}
public void setOwnerUsername(String ownerUsername) {
this.ownerUsername = ownerUsername;
}
public boolean isPublic() {
return this.isPublic;
}
public void setPublic(boolean aPublic) {
isPublic = aPublic;
}
public int getStarCount() {
return this.starCount;
}
public void setStarCount(int starCount) {
this.starCount = starCount;
}
}

View File

@ -34,7 +34,7 @@ public class SecurityConfiguration {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers("/greeting", "/auth/**", "/sign-up/**", "/recipe/**");
return web -> web.ignoring().requestMatchers("/greeting", "/auth/**", "/sign-up/**", "/recipes/**");
}
@Bean