Basic Recipe entity and models.
This commit is contained in:
		
							parent
							
								
									e205db813a
								
							
						
					
					
						commit
						b10451203b
					
				| @ -31,6 +31,14 @@ dependencies { | |||||||
| 	implementation 'io.jsonwebtoken:jjwt-api:0.12.5' | 	implementation 'io.jsonwebtoken:jjwt-api:0.12.5' | ||||||
| 	implementation 'io.jsonwebtoken:jjwt-jackson:0.12.5' | 	implementation 'io.jsonwebtoken:jjwt-jackson:0.12.5' | ||||||
| 	runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5' | 	runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5' | ||||||
|  | 
 | ||||||
|  | 	implementation 'org.commonmark:commonmark:0.22.0' | ||||||
|  | 	implementation 'org.jsoup:jsoup:1.17.2' | ||||||
|  | 
 | ||||||
|  | 	compileOnly 'org.jetbrains:annotations:24.1.0' | ||||||
|  | 
 | ||||||
|  | 	// Custom testing | ||||||
|  | 	testRuntimeOnly 'com.h2database:h2' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| tasks.named('test') { | tasks.named('test') { | ||||||
|  | |||||||
							
								
								
									
										21
									
								
								src/main/java/app/mealsmadeeasy/api/recipe/Recipe.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/main/java/app/mealsmadeeasy/api/recipe/Recipe.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.comment.RecipeComment; | ||||||
|  | import app.mealsmadeeasy.api.user.User; | ||||||
|  | import org.jetbrains.annotations.Nullable; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | public interface Recipe { | ||||||
|  |     Long getId(); | ||||||
|  |     LocalDateTime getCreated(); | ||||||
|  |     @Nullable LocalDateTime getModified(); | ||||||
|  |     String getTitle(); | ||||||
|  |     String getRawText(); | ||||||
|  |     User getOwner(); | ||||||
|  |     Set<User> getStarGazers(); | ||||||
|  |     boolean isPublic(); | ||||||
|  |     Set<User> getViewers(); | ||||||
|  |     Set<RecipeComment> getComments(); | ||||||
|  | } | ||||||
							
								
								
									
										170
									
								
								src/main/java/app/mealsmadeeasy/api/recipe/RecipeEntity.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/main/java/app/mealsmadeeasy/api/recipe/RecipeEntity.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,170 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.comment.RecipeComment; | ||||||
|  | import app.mealsmadeeasy.api.recipe.comment.RecipeCommentEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.User; | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import jakarta.persistence.*; | ||||||
|  | import org.jetbrains.annotations.Nullable; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | @Entity(name = "Recipe") | ||||||
|  | public final class RecipeEntity implements Recipe { | ||||||
|  | 
 | ||||||
|  |     @Id | ||||||
|  |     @GeneratedValue(strategy = GenerationType.AUTO) | ||||||
|  |     @Column(nullable = false, updatable = false) | ||||||
|  |     private Long id; | ||||||
|  | 
 | ||||||
|  |     @Column(nullable = false) | ||||||
|  |     private LocalDateTime created = LocalDateTime.now(); | ||||||
|  | 
 | ||||||
|  |     private LocalDateTime modified; | ||||||
|  | 
 | ||||||
|  |     @Column(nullable = false) | ||||||
|  |     private String title; | ||||||
|  | 
 | ||||||
|  |     @Column(nullable = false) | ||||||
|  |     @Lob | ||||||
|  |     @Basic(fetch = FetchType.LAZY) | ||||||
|  |     private String rawText; | ||||||
|  | 
 | ||||||
|  |     @Lob | ||||||
|  |     @Basic(fetch = FetchType.LAZY) | ||||||
|  |     private String cachedRenderedText; | ||||||
|  | 
 | ||||||
|  |     @ManyToOne(optional = false) | ||||||
|  |     @JoinColumn(name = "owner_id", nullable = false) | ||||||
|  |     private UserEntity owner; | ||||||
|  | 
 | ||||||
|  |     @OneToMany | ||||||
|  |     private Set<UserEntity> starGazers = new HashSet<>(); | ||||||
|  | 
 | ||||||
|  |     @OneToMany(mappedBy = "recipe") | ||||||
|  |     private Set<RecipeCommentEntity> comments = new HashSet<>(); | ||||||
|  | 
 | ||||||
|  |     @Column(nullable = false) | ||||||
|  |     private Boolean isPublic = false; | ||||||
|  | 
 | ||||||
|  |     @ManyToMany | ||||||
|  |     private Set<UserEntity> viewers = new HashSet<>(); | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Long getId() { | ||||||
|  |         return this.id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setId(Long id) { | ||||||
|  |         this.id = id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public LocalDateTime getCreated() { | ||||||
|  |         return this.created; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setCreated(LocalDateTime created) { | ||||||
|  |         this.created = created; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public @Nullable LocalDateTime getModified() { | ||||||
|  |         return this.modified; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setModified(@Nullable LocalDateTime modified) { | ||||||
|  |         this.modified = modified; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getTitle() { | ||||||
|  |         return this.title; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setTitle(String title) { | ||||||
|  |         this.title = title; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getRawText() { | ||||||
|  |         return this.rawText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setRawText(String rawText) { | ||||||
|  |         this.rawText = rawText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getCachedRenderedText() { | ||||||
|  |         return this.cachedRenderedText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setCachedRenderedText(String cachedRenderedText) { | ||||||
|  |         this.cachedRenderedText = cachedRenderedText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public UserEntity getOwner() { | ||||||
|  |         return this.owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setOwner(UserEntity owner) { | ||||||
|  |         this.owner = owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean isPublic() { | ||||||
|  |         return this.isPublic; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setPublic(Boolean isPublic) { | ||||||
|  |         this.isPublic = isPublic; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Set<User> getViewers() { | ||||||
|  |         return Set.copyOf(this.viewers); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<UserEntity> getViewerEntities() { | ||||||
|  |         return this.viewers; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setViewers(Set<UserEntity> viewers) { | ||||||
|  |         this.viewers = viewers; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Set<User> getStarGazers() { | ||||||
|  |         return Set.copyOf(this.starGazers); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<UserEntity> getStarGazerEntities() { | ||||||
|  |         return this.starGazers; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setStarGazers(Set<UserEntity> starGazers) { | ||||||
|  |         this.starGazers = starGazers; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Set<RecipeComment> getComments() { | ||||||
|  |         return Set.copyOf(this.comments); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<RecipeCommentEntity> getCommentEntities() { | ||||||
|  |         return this.comments; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setComments(Set<RecipeCommentEntity> comments) { | ||||||
|  |         this.comments = comments; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "RecipeEntity(" + this.id + ", " + this.title + ")"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | public class RecipeException extends Exception { | ||||||
|  | 
 | ||||||
|  |     public enum Type { | ||||||
|  |         INVALID_OWNER_USERNAME, INVALID_STAR, INVALID_ID | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private final Type type; | ||||||
|  | 
 | ||||||
|  |     public RecipeException(Type type, String message, Throwable cause) { | ||||||
|  |         super(message, cause); | ||||||
|  |         this.type = type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public RecipeException(Type type, String message) { | ||||||
|  |         super(message); | ||||||
|  |         this.type = type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Type getType() { | ||||||
|  |         return this.type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  | import org.springframework.data.jpa.repository.Query; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | public interface RecipeRepository extends JpaRepository<RecipeEntity, Long> { | ||||||
|  |     List<RecipeEntity> findAllByIsPublicIsTrue(); | ||||||
|  |     List<RecipeEntity> findAllByViewersContaining(UserEntity viewer); | ||||||
|  |     List<RecipeEntity> findAllByOwner(UserEntity owner); | ||||||
|  | 
 | ||||||
|  |     @Query("SELECT r FROM Recipe r WHERE size(r.starGazers) > ?1") | ||||||
|  |     List<RecipeEntity> findAllByStarGazersGreaterThanEqual(long stars); | ||||||
|  | } | ||||||
| @ -0,0 +1,45 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.comment.RecipeComment; | ||||||
|  | import app.mealsmadeeasy.api.recipe.star.RecipeStar; | ||||||
|  | import app.mealsmadeeasy.api.user.User; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | public interface RecipeService { | ||||||
|  | 
 | ||||||
|  |     Recipe create(String ownerUsername, String title, String rawText) throws RecipeException; | ||||||
|  | 
 | ||||||
|  |     Recipe getById(long id) throws RecipeException; | ||||||
|  |     List<Recipe> getByMinimumStars(long minimumStars); | ||||||
|  |     List<Recipe> getPublicRecipes(); | ||||||
|  |     List<Recipe> getRecipesViewableBy(User user); | ||||||
|  |     List<Recipe> getRecipesOwnedBy(User user); | ||||||
|  | 
 | ||||||
|  |     String getRenderedMarkdown(Recipe recipe); | ||||||
|  | 
 | ||||||
|  |     Recipe updateRawText(Recipe recipe, String newRawText); | ||||||
|  | 
 | ||||||
|  |     Recipe updateOwner(Recipe recipe, String newOwnerUsername) throws RecipeException; | ||||||
|  | 
 | ||||||
|  |     RecipeStar addStar(Recipe recipe, User giver); | ||||||
|  |     void deleteStarByUser(Recipe recipe, User giver) throws RecipeException; | ||||||
|  |     void deleteStar(RecipeStar recipeStar); | ||||||
|  | 
 | ||||||
|  |     Recipe setPublic(Recipe recipe, boolean isPublic); | ||||||
|  | 
 | ||||||
|  |     Recipe addViewer(Recipe recipe, User user); | ||||||
|  |     Recipe removeViewer(Recipe recipe, User user); | ||||||
|  |     Recipe clearViewers(Recipe recipe); | ||||||
|  | 
 | ||||||
|  |     RecipeComment getCommentById(long id) throws RecipeException; | ||||||
|  |     RecipeComment addComment(Recipe recipe, String rawCommentText, User commenter); | ||||||
|  |     RecipeComment updateComment(RecipeComment comment, String newRawCommentText); | ||||||
|  |     String getRenderedMarkdown(RecipeComment recipeComment); | ||||||
|  |     void deleteComment(RecipeComment comment); | ||||||
|  |     Recipe clearComments(Recipe recipe); | ||||||
|  | 
 | ||||||
|  |     void deleteRecipe(Recipe recipe); | ||||||
|  |     void deleteById(long id); | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,236 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.comment.RecipeComment; | ||||||
|  | import app.mealsmadeeasy.api.recipe.comment.RecipeCommentEntity; | ||||||
|  | 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.user.User; | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.UserRepository; | ||||||
|  | import org.commonmark.parser.Parser; | ||||||
|  | import org.commonmark.renderer.html.HtmlRenderer; | ||||||
|  | import org.jsoup.Jsoup; | ||||||
|  | import org.jsoup.safety.Safelist; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | 
 | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | @Service | ||||||
|  | public final class RecipeServiceImpl implements RecipeService { | ||||||
|  | 
 | ||||||
|  |     private static String renderAndCleanMarkdown(String rawText) { | ||||||
|  |         final var parser = Parser.builder().build(); | ||||||
|  |         final var node = parser.parse(rawText); | ||||||
|  |         final var htmlRenderer = HtmlRenderer.builder().build(); | ||||||
|  |         final String unsafeHtml = htmlRenderer.render(node); | ||||||
|  |         return Jsoup.clean(unsafeHtml, Safelist.relaxed()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private final RecipeRepository recipeRepository; | ||||||
|  |     private final UserRepository userRepository; | ||||||
|  |     private final RecipeStarRepository recipeStarRepository; | ||||||
|  |     private final RecipeCommentRepository recipeCommentRepository; | ||||||
|  | 
 | ||||||
|  |     public RecipeServiceImpl( | ||||||
|  |             RecipeRepository recipeRepository, | ||||||
|  |             UserRepository userRepository, | ||||||
|  |             RecipeStarRepository recipeStarRepository, | ||||||
|  |             RecipeCommentRepository recipeCommentRepository | ||||||
|  |     ) { | ||||||
|  |         this.recipeRepository = recipeRepository; | ||||||
|  |         this.userRepository = userRepository; | ||||||
|  |         this.recipeStarRepository = recipeStarRepository; | ||||||
|  |         this.recipeCommentRepository = recipeCommentRepository; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe create(String ownerUsername, String title, String rawText) throws RecipeException { | ||||||
|  |         final RecipeEntity draft = new RecipeEntity(); | ||||||
|  |         final UserEntity userEntity = this.userRepository.findByUsername(ownerUsername) | ||||||
|  |                 .orElseThrow(() -> new RecipeException( | ||||||
|  |                         RecipeException.Type.INVALID_OWNER_USERNAME, | ||||||
|  |                         "No such ownerUsername " + ownerUsername | ||||||
|  |                 )); | ||||||
|  |         draft.setOwner(userEntity); | ||||||
|  |         draft.setTitle(title); | ||||||
|  |         draft.setRawText(rawText); | ||||||
|  |         return this.recipeRepository.save(draft); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe getById(long id) throws RecipeException { | ||||||
|  |         return this.recipeRepository.findById(id).orElseThrow(() -> new RecipeException( | ||||||
|  |                 RecipeException.Type.INVALID_ID, | ||||||
|  |                 "No such recipe for id " + id | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<Recipe> getByMinimumStars(long minimumStars) { | ||||||
|  |         return List.copyOf(this.recipeRepository.findAllByStarGazersGreaterThanEqual(minimumStars)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<Recipe> getPublicRecipes() { | ||||||
|  |         return List.copyOf(this.recipeRepository.findAllByIsPublicIsTrue()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<Recipe> getRecipesViewableBy(User user) { | ||||||
|  |         return List.copyOf(this.recipeRepository.findAllByViewersContaining((UserEntity) user)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<Recipe> getRecipesOwnedBy(User user) { | ||||||
|  |         return List.copyOf(this.recipeRepository.findAllByOwner((UserEntity) user)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getRenderedMarkdown(Recipe recipe) { | ||||||
|  |         RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         if (entity.getCachedRenderedText() == null) { | ||||||
|  |             entity.setCachedRenderedText(renderAndCleanMarkdown(entity.getRawText())); | ||||||
|  |             entity = this.recipeRepository.save(entity); | ||||||
|  |         } | ||||||
|  |         return entity.getCachedRenderedText(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe updateRawText(Recipe recipe, String newRawText) { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         entity.setCachedRenderedText(null); | ||||||
|  |         entity.setRawText(newRawText); | ||||||
|  |         return this.recipeRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe updateOwner(Recipe recipe, String newOwnerUsername) throws RecipeException { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         final UserEntity newOwner = this.userRepository.findByUsername(newOwnerUsername) | ||||||
|  |                 .orElseThrow(() -> new RecipeException( | ||||||
|  |                         RecipeException.Type.INVALID_OWNER_USERNAME, | ||||||
|  |                         "No such username: " + newOwnerUsername | ||||||
|  |                 )); | ||||||
|  |         entity.setOwner(newOwner); | ||||||
|  |         return this.recipeRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public RecipeStar addStar(Recipe recipe, User giver) { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         final RecipeStarEntity star = new RecipeStarEntity(); | ||||||
|  |         star.setOwner((UserEntity) giver); | ||||||
|  |         star.setRecipe(entity); | ||||||
|  |         return this.recipeStarRepository.save(star); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void deleteStar(RecipeStar recipeStar) { | ||||||
|  |         this.recipeStarRepository.delete((RecipeStarEntity) recipeStar); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void deleteStarByUser(Recipe recipe, User giver) throws RecipeException { | ||||||
|  |         final RecipeStarEntity star = this.recipeStarRepository.findByOwnerAndRecipe( | ||||||
|  |                         (UserEntity) giver, | ||||||
|  |                         (RecipeEntity) recipe | ||||||
|  |                 ).orElseThrow(() -> new RecipeException( | ||||||
|  |                         RecipeException.Type.INVALID_STAR, | ||||||
|  |                         "No such star for user " + giver.getUsername() + " and recipe " + recipe.getId() | ||||||
|  |                 )); | ||||||
|  |         this.recipeStarRepository.delete(star); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe setPublic(Recipe recipe, boolean isPublic) { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         entity.setPublic(isPublic); | ||||||
|  |         return this.recipeRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe addViewer(Recipe recipe, User user) { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         final Set<UserEntity> viewers = new HashSet<>(entity.getViewerEntities()); | ||||||
|  |         viewers.add((UserEntity) user); | ||||||
|  |         entity.setViewers(viewers); | ||||||
|  |         return this.recipeRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe removeViewer(Recipe recipe, User user) { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         final Set<UserEntity> viewers = new HashSet<>(entity.getViewerEntities()); | ||||||
|  |         viewers.remove((UserEntity) user); | ||||||
|  |         entity.setViewers(viewers); | ||||||
|  |         return this.recipeRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe clearViewers(Recipe recipe) { | ||||||
|  |         final RecipeEntity entity = (RecipeEntity) recipe; | ||||||
|  |         entity.setViewers(new HashSet<>()); | ||||||
|  |         return this.recipeRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public RecipeComment getCommentById(long id) throws RecipeException { | ||||||
|  |         return this.recipeCommentRepository.findById(id) | ||||||
|  |                 .orElseThrow(() -> new RecipeException( | ||||||
|  |                         RecipeException.Type.INVALID_ID, | ||||||
|  |                         "No such RecipeComment for id " + id | ||||||
|  |                 )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public RecipeComment addComment(Recipe recipe, String rawCommentText, User commenter) { | ||||||
|  |         final RecipeCommentEntity draft = new RecipeCommentEntity(); | ||||||
|  |         draft.setRawText(rawCommentText); | ||||||
|  |         draft.setOwner((UserEntity) commenter); | ||||||
|  |         return this.recipeCommentRepository.save(draft); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public RecipeComment updateComment(RecipeComment comment, String newRawCommentText) { | ||||||
|  |         final RecipeCommentEntity entity = (RecipeCommentEntity) comment; | ||||||
|  |         entity.setCachedRenderedText(null); | ||||||
|  |         entity.setRawText(newRawCommentText); | ||||||
|  |         return this.recipeCommentRepository.save(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getRenderedMarkdown(RecipeComment recipeComment) { | ||||||
|  |         RecipeCommentEntity entity = (RecipeCommentEntity) recipeComment; | ||||||
|  |         if (entity.getCachedRenderedText() == null) { | ||||||
|  |             entity.setCachedRenderedText(renderAndCleanMarkdown(entity.getRawText())); | ||||||
|  |             entity = this.recipeCommentRepository.save(entity); | ||||||
|  |         } | ||||||
|  |         return entity.getCachedRenderedText(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void deleteComment(RecipeComment comment) { | ||||||
|  |         this.recipeCommentRepository.delete((RecipeCommentEntity) comment); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Recipe clearComments(Recipe recipe) { | ||||||
|  |         this.recipeCommentRepository.deleteAllByRecipe((RecipeEntity) recipe); | ||||||
|  |         return this.recipeRepository.getReferenceById(recipe.getId()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void deleteRecipe(Recipe recipe) { | ||||||
|  |         this.recipeRepository.delete((RecipeEntity) recipe); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void deleteById(long id) { | ||||||
|  |         this.recipeRepository.deleteById(id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe.comment; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.Recipe; | ||||||
|  | import app.mealsmadeeasy.api.user.User; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | 
 | ||||||
|  | public interface RecipeComment { | ||||||
|  |     LocalDateTime getCreated(); | ||||||
|  |     LocalDateTime getModified(); | ||||||
|  |     String getRawText(); | ||||||
|  |     User getOwner(); | ||||||
|  |     Recipe getRecipe(); | ||||||
|  | } | ||||||
| @ -0,0 +1,99 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe.comment; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.RecipeEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import jakarta.persistence.*; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | 
 | ||||||
|  | @Entity(name = "RecipeComment") | ||||||
|  | public final class RecipeCommentEntity implements RecipeComment { | ||||||
|  | 
 | ||||||
|  |     @Id | ||||||
|  |     @GeneratedValue(strategy = GenerationType.AUTO) | ||||||
|  |     @Column(nullable = false) | ||||||
|  |     private Long id; | ||||||
|  | 
 | ||||||
|  |     @Column(nullable = false, updatable = false) | ||||||
|  |     private LocalDateTime created = LocalDateTime.now(); | ||||||
|  | 
 | ||||||
|  |     private LocalDateTime modified; | ||||||
|  | 
 | ||||||
|  |     @Lob | ||||||
|  |     @Basic(fetch = FetchType.LAZY) | ||||||
|  |     private String rawText; | ||||||
|  | 
 | ||||||
|  |     @Lob | ||||||
|  |     @Basic(fetch = FetchType.LAZY) | ||||||
|  |     private String cachedRenderedText; | ||||||
|  | 
 | ||||||
|  |     @ManyToOne | ||||||
|  |     @JoinColumn(name = "owner_id", nullable = false, updatable = false) | ||||||
|  |     private UserEntity owner; | ||||||
|  | 
 | ||||||
|  |     @ManyToOne | ||||||
|  |     @JoinColumn(name = "recipe_id", nullable = false, updatable = false) | ||||||
|  |     private RecipeEntity recipe; | ||||||
|  | 
 | ||||||
|  |     public Long getId() { | ||||||
|  |         return this.id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setId(Long id) { | ||||||
|  |         this.id = id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public LocalDateTime getCreated() { | ||||||
|  |         return this.created; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setCreated(LocalDateTime created) { | ||||||
|  |         this.created = created; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public LocalDateTime getModified() { | ||||||
|  |         return this.modified; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setModified(LocalDateTime modified) { | ||||||
|  |         this.modified = modified; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String getRawText() { | ||||||
|  |         return this.rawText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setRawText(String rawText) { | ||||||
|  |         this.rawText = rawText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getCachedRenderedText() { | ||||||
|  |         return this.cachedRenderedText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setCachedRenderedText(String cachedRenderedText) { | ||||||
|  |         this.cachedRenderedText = cachedRenderedText; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public UserEntity getOwner() { | ||||||
|  |         return this.owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setOwner(UserEntity owner) { | ||||||
|  |         this.owner = owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public RecipeEntity getRecipe() { | ||||||
|  |         return this.recipe; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setRecipe(RecipeEntity recipe) { | ||||||
|  |         this.recipe = recipe; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,8 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe.comment; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.RecipeEntity; | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  | 
 | ||||||
|  | public interface RecipeCommentRepository extends JpaRepository<RecipeCommentEntity, Long> { | ||||||
|  |     void deleteAllByRecipe(RecipeEntity recipe); | ||||||
|  | } | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe.star; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.Recipe; | ||||||
|  | import app.mealsmadeeasy.api.user.User; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | 
 | ||||||
|  | public interface RecipeStar { | ||||||
|  |     User getOwner(); | ||||||
|  |     LocalDateTime getDate(); | ||||||
|  |     Recipe getRecipe(); | ||||||
|  | } | ||||||
| @ -0,0 +1,63 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe.star; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.RecipeEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import jakarta.persistence.*; | ||||||
|  | 
 | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | 
 | ||||||
|  | @Entity(name = "RecipeStar") | ||||||
|  | public final class RecipeStarEntity implements RecipeStar { | ||||||
|  | 
 | ||||||
|  |     @Id | ||||||
|  |     @GeneratedValue(strategy = GenerationType.AUTO) | ||||||
|  |     @Column(nullable = false) | ||||||
|  |     private Long id; | ||||||
|  | 
 | ||||||
|  |     @ManyToOne | ||||||
|  |     @JoinColumn(name = "owner_id", nullable = false, updatable = false) | ||||||
|  |     private UserEntity owner; | ||||||
|  | 
 | ||||||
|  |     @Column(nullable = false, updatable = false) | ||||||
|  |     private LocalDateTime date = LocalDateTime.now(); | ||||||
|  | 
 | ||||||
|  |     @ManyToOne | ||||||
|  |     @JoinColumn(name = "recipe_id", nullable = false, updatable = false) | ||||||
|  |     private RecipeEntity recipe; | ||||||
|  | 
 | ||||||
|  |     public long getId() { | ||||||
|  |         return this.id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setId(long id) { | ||||||
|  |         this.id = id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public UserEntity getOwner() { | ||||||
|  |         return this.owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setOwner(UserEntity owner) { | ||||||
|  |         this.owner = owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public LocalDateTime getDate() { | ||||||
|  |         return this.date; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setDate(LocalDateTime date) { | ||||||
|  |         this.date = date; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public RecipeEntity getRecipe() { | ||||||
|  |         return this.recipe; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setRecipe(RecipeEntity recipe) { | ||||||
|  |         this.recipe = recipe; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe.star; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.recipe.RecipeEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Optional; | ||||||
|  | 
 | ||||||
|  | public interface RecipeStarRepository extends JpaRepository<RecipeStarEntity, Long> { | ||||||
|  |     List<RecipeStarEntity> findAllByOwner(UserEntity user); | ||||||
|  |     long countAllByOwner(UserEntity user); | ||||||
|  |     Optional<RecipeStarEntity> findByOwnerAndRecipe(UserEntity user, RecipeEntity recipe); | ||||||
|  | } | ||||||
| @ -5,9 +5,11 @@ import org.springframework.security.core.GrantedAuthority; | |||||||
| 
 | 
 | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
|  | import java.util.Objects; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
| @Entity(name = "User") | @Entity(name = "User") | ||||||
|  | @Table(name = "\"user\"") | ||||||
| public final class UserEntity implements User { | public final class UserEntity implements User { | ||||||
| 
 | 
 | ||||||
|     public static UserEntity getDefaultDraft() { |     public static UserEntity getDefaultDraft() { | ||||||
| @ -141,4 +143,41 @@ public final class UserEntity implements User { | |||||||
|         this.enabled = enabled; |         this.enabled = enabled; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         return Objects.hash( | ||||||
|  |                 this.id, | ||||||
|  |                 this.username, | ||||||
|  |                 this.email, | ||||||
|  |                 this.password, | ||||||
|  |                 this.authorities, | ||||||
|  |                 this.enabled, | ||||||
|  |                 this.expired, | ||||||
|  |                 this.locked, | ||||||
|  |                 this.credentialsExpired | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(Object obj) { | ||||||
|  |         if (this == obj) return true; | ||||||
|  |         if (obj instanceof User o) { | ||||||
|  |             return Objects.equals(this.id, o.getId()) | ||||||
|  |                     && Objects.equals(this.username, o.getUsername()) | ||||||
|  |                     && Objects.equals(this.password, o.getPassword()) | ||||||
|  |                     && Objects.equals(this.authorities, o.getAuthorities()) | ||||||
|  |                     && Objects.equals(this.enabled, o.isEnabled()) | ||||||
|  |                     && Objects.equals(this.expired, !o.isAccountNonExpired()) | ||||||
|  |                     && Objects.equals(this.locked, !o.isAccountNonLocked()) | ||||||
|  |                     && Objects.equals(this.credentialsExpired, !o.isCredentialsNonExpired()); | ||||||
|  |         } else { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "User(" + this.id + ", " + this.username + ", " + this.email + ")"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,102 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.UserRepository; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  | import org.springframework.test.annotation.DirtiesContext; | ||||||
|  | 
 | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | 
 | ||||||
|  | @SpringBootTest | ||||||
|  | public class RecipeRepositoryTests { | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private RecipeRepository recipeRepository; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private UserRepository userRepository; | ||||||
|  | 
 | ||||||
|  |     private UserEntity getOwnerUser() { | ||||||
|  |         final UserEntity recipeUser = UserEntity.getDefaultDraft(); | ||||||
|  |         recipeUser.setUsername("recipeUser"); | ||||||
|  |         recipeUser.setEmail("recipe@user.com"); | ||||||
|  |         recipeUser.setPassword("test"); | ||||||
|  |         return this.userRepository.save(recipeUser); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private UserEntity getViewerUser() { | ||||||
|  |         final UserEntity viewerUser = UserEntity.getDefaultDraft(); | ||||||
|  |         viewerUser.setUsername("recipeViewerUser"); | ||||||
|  |         viewerUser.setEmail("recipe-viewer@user.com"); | ||||||
|  |         viewerUser.setPassword("test"); | ||||||
|  |         return this.userRepository.save(viewerUser); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DirtiesContext | ||||||
|  |     public void findsAllPublicRecipes() { | ||||||
|  |         final RecipeEntity publicRecipe = new RecipeEntity(); | ||||||
|  |         publicRecipe.setPublic(true); | ||||||
|  |         publicRecipe.setOwner(this.getOwnerUser()); | ||||||
|  |         publicRecipe.setTitle("Public Recipe"); | ||||||
|  |         publicRecipe.setRawText("Hello, World!"); | ||||||
|  |         this.recipeRepository.save(publicRecipe); | ||||||
|  | 
 | ||||||
|  |         final List<RecipeEntity> publicRecipes = this.recipeRepository.findAllByIsPublicIsTrue(); | ||||||
|  |         assertThat(publicRecipes.size()).isEqualTo(1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DirtiesContext | ||||||
|  |     public void doesNotFindNonPublicRecipe() { | ||||||
|  |         final RecipeEntity nonPublicRecipe = new RecipeEntity(); | ||||||
|  |         nonPublicRecipe.setOwner(this.getOwnerUser()); | ||||||
|  |         nonPublicRecipe.setTitle("Non-Public Recipe"); | ||||||
|  |         nonPublicRecipe.setRawText("Hello, World!"); | ||||||
|  |         this.recipeRepository.save(nonPublicRecipe); | ||||||
|  | 
 | ||||||
|  |         final List<RecipeEntity> publicRecipes = this.recipeRepository.findAllByIsPublicIsTrue(); | ||||||
|  |         assertThat(publicRecipes.size()).isEqualTo(0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DirtiesContext | ||||||
|  |     public void findsAllForViewer() { | ||||||
|  |         final RecipeEntity recipe = new RecipeEntity(); | ||||||
|  |         recipe.setOwner(this.getOwnerUser()); | ||||||
|  |         recipe.setTitle("Test Recipe"); | ||||||
|  |         recipe.setRawText("Hello, World!"); | ||||||
|  |         final RecipeEntity saved = this.recipeRepository.save(recipe); | ||||||
|  | 
 | ||||||
|  |         final UserEntity viewer = this.getViewerUser(); | ||||||
|  |         final Set<UserEntity> viewers = new HashSet<>(recipe.getViewerEntities()); | ||||||
|  |         viewers.add(viewer); | ||||||
|  |         saved.setViewers(viewers); | ||||||
|  | 
 | ||||||
|  |         this.recipeRepository.save(saved); | ||||||
|  | 
 | ||||||
|  |         final List<RecipeEntity> viewable = this.recipeRepository.findAllByViewersContaining(viewer); | ||||||
|  |         assertThat(viewable.size()).isEqualTo(1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DirtiesContext | ||||||
|  |     public void doesNotIncludeNonViewable() { | ||||||
|  |         final RecipeEntity recipe = new RecipeEntity(); | ||||||
|  |         recipe.setOwner(this.getOwnerUser()); | ||||||
|  |         recipe.setTitle("Test Recipe"); | ||||||
|  |         recipe.setRawText("Hello, World!"); | ||||||
|  |         this.recipeRepository.save(recipe); | ||||||
|  | 
 | ||||||
|  |         final UserEntity viewer = this.getViewerUser(); | ||||||
|  |         final List<RecipeEntity> viewable = this.recipeRepository.findAllByViewersContaining(viewer); | ||||||
|  |         assertThat(viewable.size()).isEqualTo(0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,55 @@ | |||||||
|  | package app.mealsmadeeasy.api.recipe; | ||||||
|  | 
 | ||||||
|  | import app.mealsmadeeasy.api.user.User; | ||||||
|  | import app.mealsmadeeasy.api.user.UserEntity; | ||||||
|  | import app.mealsmadeeasy.api.user.UserRepository; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  | import org.springframework.test.annotation.DirtiesContext; | ||||||
|  | 
 | ||||||
|  | import static org.hamcrest.MatcherAssert.assertThat; | ||||||
|  | import static org.hamcrest.Matchers.is; | ||||||
|  | 
 | ||||||
|  | @SpringBootTest | ||||||
|  | public class RecipeServiceTests { | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private RecipeService recipeService; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private UserRepository userRepository; | ||||||
|  | 
 | ||||||
|  |     private UserEntity createTestUser(String username) { | ||||||
|  |         final UserEntity draft = UserEntity.getDefaultDraft(); | ||||||
|  |         draft.setUsername(username); | ||||||
|  |         draft.setEmail(username + "@test.com"); | ||||||
|  |         draft.setPassword("test"); | ||||||
|  |         return this.userRepository.save(draft); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Recipe createTestRecipe(User owner) throws RecipeException { | ||||||
|  |         return this.recipeService.create(owner.getUsername(), "My Recipe" , "Hello!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DirtiesContext | ||||||
|  |     public void simpleCreate() throws RecipeException { | ||||||
|  |         final User user = this.createTestUser("recipeOwner"); | ||||||
|  |         final Recipe recipe = this.recipeService.create(user.getUsername(), "My Recipe" , "Hello!"); | ||||||
|  |         assertThat(recipe.getOwner(), is(user)); | ||||||
|  |         assertThat(recipe.getTitle(), is("My Recipe")); | ||||||
|  |         assertThat(recipe.getRawText(), is("Hello!")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @DirtiesContext | ||||||
|  |     public void simpleGetById() throws RecipeException { | ||||||
|  |         final Recipe testRecipe = this.createTestRecipe(this.createTestUser("recipeOwner")); | ||||||
|  |         final Recipe byId = this.recipeService.getById(testRecipe.getId()); | ||||||
|  |         assertThat(byId.getId(), is(testRecipe.getId())); | ||||||
|  |         assertThat(byId.getTitle(), is("My Recipe")); | ||||||
|  |         assertThat(byId.getRawText(), is("Hello!")); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								src/test/resources/application.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/test/resources/application.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | spring.datasource.driver-class-name=org.h2.Driver | ||||||
|  | spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 | ||||||
|  | spring.datasource.username=sa | ||||||
|  | spring.datasource.password=sa | ||||||
|  | app.mealsmadeeasy.api.security.access-token-lifetime=60 | ||||||
|  | app.mealsmadeeasy.api.security.refresh-token-lifetime=120 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 JesseBrault0709
						JesseBrault0709