meals-made-easy-api/src/main/java/app/mealsmadeeasy/api/recipe/comment/RecipeCommentServiceImpl.java

108 lines
4.7 KiB
Java

package app.mealsmadeeasy.api.recipe.comment;
import app.mealsmadeeasy.api.markdown.MarkdownService;
import app.mealsmadeeasy.api.recipe.RecipeEntity;
import app.mealsmadeeasy.api.recipe.RecipeException;
import app.mealsmadeeasy.api.recipe.RecipeRepository;
import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserEntity;
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;
import java.time.OffsetDateTime;
import static java.util.Objects.requireNonNull;
@Service
public class RecipeCommentServiceImpl implements RecipeCommentService {
private final RecipeCommentRepository recipeCommentRepository;
private final RecipeRepository recipeRepository;
private final MarkdownService markdownService;
public RecipeCommentServiceImpl(
RecipeCommentRepository recipeCommentRepository,
RecipeRepository recipeRepository,
MarkdownService markdownService
) {
this.recipeCommentRepository = recipeCommentRepository;
this.recipeRepository = recipeRepository;
this.markdownService = markdownService;
}
@Override
@PreAuthorize("@recipeSecurity.isViewableBy(#recipeUsername, #recipeSlug, #commenter)")
public RecipeComment create(
String recipeUsername,
String recipeSlug,
User commenter,
RecipeCommentCreateBody body
) throws RecipeException {
requireNonNull(commenter);
final RecipeCommentEntity draft = new RecipeCommentEntity();
draft.setCreated(OffsetDateTime.now());
draft.setRawText(body.getText());
draft.setCachedRenderedText(this.markdownService.renderAndCleanMarkdown(body.getText()));
draft.setOwner((UserEntity) commenter);
final RecipeEntity recipe = this.recipeRepository.findByOwnerUsernameAndSlug(recipeUsername, recipeSlug)
.orElseThrow(() -> new RecipeException(
RecipeException.Type.INVALID_USERNAME_OR_SLUG,
"Invalid username or slug: " + recipeUsername + "/" + recipeSlug
));
draft.setRecipe(recipe);
return this.recipeCommentRepository.save(draft);
}
@PostAuthorize("@recipeSecurity.isViewableBy(returnObject.recipe, #viewer)")
private RecipeCommentEntity loadCommentEntity(long 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 {
return this.loadCommentEntity(commentId, viewer);
}
@Override
@PreAuthorize("@recipeSecurity.isViewableBy(#recipeUsername, #recipeSlug, #viewer)")
public Slice<RecipeCommentView> getComments(String recipeUsername, String recipeSlug, Pageable pageable, User viewer) throws RecipeException {
final RecipeEntity recipe = this.recipeRepository.findByOwnerUsernameAndSlug(recipeUsername, recipeSlug).orElseThrow(
() -> new RecipeException(
RecipeException.Type.INVALID_USERNAME_OR_SLUG,
"No such Recipe for username/slug: " + recipeUsername + "/" + recipeSlug
)
);
final Slice<RecipeCommentEntity> commentEntities = this.recipeCommentRepository.findAllByRecipe(recipe, pageable);
return commentEntities.map(commentEntity -> RecipeCommentView.from(
commentEntity,
false
));
}
@Override
public RecipeComment update(long commentId, User viewer, RecipeCommentUpdateSpec spec) throws RecipeException {
final RecipeCommentEntity entity = this.loadCommentEntity(commentId, viewer);
entity.setRawText(spec.getRawText());
return this.recipeCommentRepository.save(entity);
}
@PostAuthorize("@recipeSecurity.isOwner(returnObject.recipe, #modifier)")
private RecipeCommentEntity loadForDelete(long 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 {
final RecipeCommentEntity entityToDelete = this.loadForDelete(commentId, modifier);
this.recipeCommentRepository.delete(entityToDelete);
}
}