diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/Content.java b/src/main/java/cat/udl/eps/softarch/demo/domain/Content.java index 2fa1b24a..edde7ada 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/Content.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/Content.java @@ -4,16 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIdentityReference; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; +import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; @@ -37,10 +28,17 @@ public class Content { @Column(nullable = false) private Project project;*/ - /*@ManyToOne - @JsonIdentityReference(alwaysAsId = true) - @Column(nullable = false) - private User user;*/ + @ManyToMany + @JoinTable( + name = "content_tags", + joinColumns = @JoinColumn(name = "content_id"), + inverseJoinColumns = @JoinColumn(name = "tag_id") + ) + private List tags; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; @NotBlank(message = "Name cannot be empty") @Column(unique = true, nullable = false) @@ -53,13 +51,10 @@ public class Content { @Column(length = 100) private String description; - @Column(nullable = false, updatable = false) private ZonedDateTime createdAt; - @Column(nullable = false, updatable = false) private ZonedDateTime modifiedAt; @Enumerated(EnumType.STRING) @Column(nullable = false) private Visibility visibility; - } \ No newline at end of file diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/Tag.java b/src/main/java/cat/udl/eps/softarch/demo/domain/Tag.java index 871351ab..7dea84fc 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/Tag.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/Tag.java @@ -1,5 +1,6 @@ package cat.udl.eps.softarch.demo.domain; +import com.fasterxml.jackson.annotation.JsonIdentityReference; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -24,7 +25,4 @@ public class Tag extends UriEntity { private ZonedDateTime created; private ZonedDateTime modified; - - //@ManyToMany(mappedBy = "tags") - //private Set contentSet = new HashSet<>(); } diff --git a/src/main/java/cat/udl/eps/softarch/demo/repository/ContentRepository.java b/src/main/java/cat/udl/eps/softarch/demo/repository/ContentRepository.java index da77a057..4e354176 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/repository/ContentRepository.java +++ b/src/main/java/cat/udl/eps/softarch/demo/repository/ContentRepository.java @@ -19,6 +19,7 @@ public interface ContentRepository extends CrudRepository findAll(); + List findByTags_Id(Long tagId); //List findByProjectId(Long projectId); diff --git a/src/main/java/cat/udl/eps/softarch/demo/repository/TagRepository.java b/src/main/java/cat/udl/eps/softarch/demo/repository/TagRepository.java index 38a0a75c..2e72a960 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/repository/TagRepository.java +++ b/src/main/java/cat/udl/eps/softarch/demo/repository/TagRepository.java @@ -12,4 +12,5 @@ public interface TagRepository extends CrudRepository { boolean existsById(Long id); boolean existsByName(String name); Optional findByName(String name); + Optional findById(Long id); } diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/TagOwnershipStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/TagOwnershipStepDefs.java new file mode 100644 index 00000000..921df7c4 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/TagOwnershipStepDefs.java @@ -0,0 +1,108 @@ +package cat.udl.eps.softarch.demo.steps; + +import cat.udl.eps.softarch.demo.domain.Tag; +import cat.udl.eps.softarch.demo.domain.Content; +import cat.udl.eps.softarch.demo.domain.User; +import cat.udl.eps.softarch.demo.domain.Visibility; +import cat.udl.eps.softarch.demo.repository.TagRepository; +import cat.udl.eps.softarch.demo.repository.ContentRepository; +import cat.udl.eps.softarch.demo.repository.UserRepository; + +import io.cucumber.java.en.*; +import jakarta.transaction.Transactional; + +import java.time.ZonedDateTime; + +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +public class TagOwnershipStepDefs { + + private final StepDefs stepDefs; + private final TagRepository tagRepository; + private final ContentRepository contentRepository; + private final UserRepository userRepository; + + private Tag tag; + private Content content; + + public TagOwnershipStepDefs(StepDefs stepDefs, + TagRepository tagRepository, + ContentRepository contentRepository, + UserRepository userRepository) { + this.stepDefs = stepDefs; + this.tagRepository = tagRepository; + this.contentRepository = contentRepository; + this.userRepository = userRepository; + } + + @Given("there is a content {string} created by {string}") + public void thereIsAContentCreatedBy(String contentName, String username) { + + User user = userRepository.findById(username) + .orElseThrow(() -> new RuntimeException("User not found")); + + content = new Content(); + content.setName(contentName); + content.setUser(user); + content.setCreatedAt(ZonedDateTime.now()); + content.setModifiedAt(ZonedDateTime.now()); + content.setVisibility(Visibility.PUBLIC); + + content = contentRepository.save(content); + } + + @When("I assign the tag {string} to content {string}") + public void iAssignTagToContent(String tagName, String contentName) throws Exception { + + Tag tagEntity = tagRepository.findByName(tagName) + .orElseThrow(() -> new RuntimeException("Tag not found")); + + Content contentEntity = contentRepository.findById(content.getContentId()) + .orElseThrow(() -> new RuntimeException("Content not found")); + + String authenticatedUsername = "creator1"; + + if (!contentEntity.getUser().getUsername().equals(authenticatedUsername)) { + stepDefs.result = stepDefs.mockMvc.perform( + post("/contents/" + contentEntity.getContentId() + "/tags") + .contentType("text/uri-list") + .content("/tags/" + tagEntity.getId()) + .with(user(authenticatedUsername)) + ).andDo(print()) + .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().isForbidden()); + return; + } + + stepDefs.result = stepDefs.mockMvc.perform( + post("/contents/" + contentEntity.getContentId() + "/tags") + .contentType("text/uri-list") + .content("/tags/" + tagEntity.getId()) + .with(user(authenticatedUsername)) + ).andDo(print()) + .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().isNoContent()); + } + + @Then("The response status is {int}") + public void theResponseStatusIs(int status) throws Exception { + stepDefs.result.andExpect( + org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().is(status) + ); + } + + @Then("content {string} should contain tag {string}") + @Transactional + public void contentShouldContainTag(String contentName, String tagName) { + + Content updatedContent = contentRepository.findById(content.getContentId()) + .orElseThrow(() -> new RuntimeException("Content not found")); + + boolean exists = updatedContent.getTags() + .stream() + .anyMatch(t -> t.getName().equals(tagName)); + + assertTrue(exists, "Tag not assigned correctly to content"); + } +} \ No newline at end of file