diff --git a/content-service/src/main/java/io/meeds/news/model/News.java b/content-service/src/main/java/io/meeds/news/model/News.java index c7d9c8c3f..2d7c19dbd 100644 --- a/content-service/src/main/java/io/meeds/news/model/News.java +++ b/content-service/src/main/java/io/meeds/news/model/News.java @@ -139,4 +139,6 @@ public class News { private List targets; private boolean favorite; + + private boolean deleted; } diff --git a/content-service/src/main/java/io/meeds/news/rest/NewsRestResourcesV1.java b/content-service/src/main/java/io/meeds/news/rest/NewsRestResourcesV1.java index 247be9fd7..8eaedceb7 100644 --- a/content-service/src/main/java/io/meeds/news/rest/NewsRestResourcesV1.java +++ b/content-service/src/main/java/io/meeds/news/rest/NewsRestResourcesV1.java @@ -405,7 +405,7 @@ public Response getNewsById(@Context } org.exoplatform.services.security.Identity currentIdentity = ConversationState.getCurrent().getIdentity(); News news = newsService.getNewsById(id, currentIdentity, editMode, newsObjectType); - if (news == null) { + if (news == null || news.isDeleted()) { return Response.status(Response.Status.NOT_FOUND).build(); } Locale userLocale = LocalizationFilter.getCurrentLocale(); diff --git a/content-service/src/main/java/io/meeds/news/service/impl/NewsServiceImpl.java b/content-service/src/main/java/io/meeds/news/service/impl/NewsServiceImpl.java index c2cabc728..72f7a32ca 100644 --- a/content-service/src/main/java/io/meeds/news/service/impl/NewsServiceImpl.java +++ b/content-service/src/main/java/io/meeds/news/service/impl/NewsServiceImpl.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.Set; import java.util.regex.Matcher; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; @@ -212,7 +213,7 @@ public News createNews(News news, Identity currentIdentity) throws Exception { Space space = spaceService.getSpaceById(news.getSpaceId()); try { if (!canCreateNews(space, currentIdentity)) { - throw new IllegalArgumentException("User " + currentIdentity.getUserId() + " not authorized to create news"); + throw new IllegalAccessException("User " + currentIdentity.getUserId() + " not authorized to create news"); } News createdNews; if (PUBLISHED.equals(news.getPublicationState())) { @@ -266,7 +267,7 @@ public News updateNews(News news, String updater, Boolean post, boolean publish) public News updateNews(News news, String updater, Boolean post, boolean publish, String newsObjectType) throws Exception { if (!canEditNews(news, updater)) { - throw new IllegalArgumentException("User " + updater + " is not authorized to update news"); + throw new IllegalAccessException("User " + updater + " is not authorized to update news"); } Identity updaterIdentity = NewsUtils.getUserIdentity(updater); News originalNews = getNewsById(news.getId(), updaterIdentity, false, newsObjectType); @@ -334,15 +335,15 @@ public void deleteNews(String newsId, Identity currentIdentity, boolean isDraft) false, isDraft ? NewsObjectType.DRAFT.name().toLowerCase() : NewsObjectType.ARTICLE.name().toLowerCase()); if (!news.isCanDelete()) { - throw new IllegalArgumentException("User " + currentIdentity.getUserId() + " is not authorized to delete news"); + throw new IllegalAccessException("User " + currentIdentity.getUserId() + " is not authorized to delete news"); } if (isDraft) { deleteDraftArticle(newsId, currentIdentity.getUserId(), true); } else { - // TODO delete article - indexingService.unindex(NewsIndexingServiceConnector.TYPE, String.valueOf(news.getId())); + deleteArticle(news, currentIdentity); MetadataObject newsMetadataObject = new MetadataObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, newsId); metadataService.deleteMetadataItemsByObject(newsMetadataObject); + indexingService.unindex(NewsIndexingServiceConnector.TYPE, String.valueOf(news.getId())); NewsUtils.broadcastEvent(NewsUtils.DELETE_NEWS, currentIdentity.getUserId(), news); } } @@ -1608,6 +1609,7 @@ private News buildArticle(String newsId) throws WikiException { } else { news.setActivityPosted(false); } + news.setDeleted(articlePage.isDeleted()); } // fetch the last version of the given lang @@ -1835,4 +1837,30 @@ private News buildLatestDraftArticle(String parentPageId, String currentIdentity draftArticle.setId(parentPageId); return draftArticle; } + + private void deleteArticle(News news, Identity currentIdentity) throws Exception { + Page articlePage = noteService.getNoteById(news.getId()); + if (articlePage != null && !articlePage.isDeleted()) { + boolean hasDraft = true; + while (hasDraft) { + try { + DraftPage latestDraftPage = noteService.getLatestDraftOfPage(articlePage, currentIdentity.getUserId()); + if (latestDraftPage != null) { + deleteDraftArticle(latestDraftPage.getId(), currentIdentity.getUserId(), true); + } else { + hasDraft = false; + } + } catch (Exception exception) { + hasDraft = false; + } + } + boolean isDeleted = noteService.deleteNote(articlePage.getWikiType(), articlePage.getWikiOwner(), articlePage.getName()); + if (isDeleted) { + if (news.getActivities() != null) { + String newsActivities = news.getActivities(); + Stream.of(newsActivities.split(";")).map(activity -> activity.split(":")[1]).forEach(activityManager::deleteActivity); + } + } + } + } } diff --git a/content-service/src/test/java/io/meeds/news/service/impl/NewsServiceImplTest.java b/content-service/src/test/java/io/meeds/news/service/impl/NewsServiceImplTest.java index 4b75661b9..4fb149aab 100644 --- a/content-service/src/test/java/io/meeds/news/service/impl/NewsServiceImplTest.java +++ b/content-service/src/test/java/io/meeds/news/service/impl/NewsServiceImplTest.java @@ -19,6 +19,7 @@ */ package io.meeds.news.service.impl; +import static io.meeds.news.service.impl.NewsServiceImpl.NEWS_ACTIVITIES; import static io.meeds.news.service.impl.NewsServiceImpl.NEWS_ARTICLES_ROOT_NOTE_PAGE_NAME; import static io.meeds.news.service.impl.NewsServiceImpl.NEWS_SUMMARY; import static org.junit.Assert.assertEquals; @@ -319,7 +320,7 @@ public void testUpdateDraftArticle() throws Exception { expecteddraftPage.setWikiOwner("/space/groupId"); // When, Then - assertThrows(IllegalArgumentException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); + assertThrows(IllegalAccessException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); // Given when(spaceService.canRedactOnSpace(space, identity)).thenReturn(true); @@ -566,7 +567,7 @@ public void testCreateDraftArticleForExistingPage() throws Exception { news.setOriginalBody("body"); // When, Then - assertThrows(IllegalArgumentException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); + assertThrows(IllegalAccessException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); // Given when(spaceService.canRedactOnSpace(space, identity)).thenReturn(true); @@ -658,7 +659,7 @@ public void testUpdateDraftArticleForExistingPage() throws Exception { news.setOriginalBody("body"); // When, Then - assertThrows(IllegalArgumentException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); + assertThrows(IllegalAccessException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); // Given when(spaceService.canRedactOnSpace(space, identity)).thenReturn(true); @@ -745,7 +746,7 @@ public void testUpdateNewsArticle() throws Exception { news.setOriginalBody("body"); // When, Then - assertThrows(IllegalArgumentException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); + assertThrows(IllegalAccessException.class, () -> newsService.updateNews(news, "john", false, false, "draft")); // Given when(spaceService.canRedactOnSpace(space, identity)).thenReturn(true); @@ -766,4 +767,65 @@ public void testUpdateNewsArticle() throws Exception { verify(noteService, times(2)).getPublishedVersionByPageIdAndLang(1L, null); verify(metadataService, times(1)).updateMetadataItem(any(MetadataItem.class), anyLong()); } + + @Test + public void testDeleteNewsArticle() throws Exception { + // Given + Page existingPage = mock(Page.class); + when(noteService.getNoteById(anyString())).thenReturn(existingPage); + when(existingPage.getId()).thenReturn("1"); + when(existingPage.getWikiOwner()).thenReturn("/space/groupId"); + when(existingPage.getWikiType()).thenReturn("group"); + when(existingPage.getName()).thenReturn("news"); + + MetadataItem metadataItem = mock(MetadataItem.class); + List metadataItems = new ArrayList<>(); + metadataItems.add(metadataItem); + when(metadataService.getMetadataItemsByMetadataAndObject(any(MetadataKey.class), + any(MetadataObject.class))).thenReturn(metadataItems); + Map properties = new HashMap<>(); + properties.put(NEWS_ACTIVITIES, "1:1;"); + when(metadataItem.getProperties()).thenReturn(properties); + + Space space = mock(Space.class); + when(space.getId()).thenReturn("1"); + when(space.getGroupId()).thenReturn("/space/groupId"); + when(space.getAvatarUrl()).thenReturn("space/avatar/url"); + when(space.getDisplayName()).thenReturn("spaceDisplayName"); + when(space.getVisibility()).thenReturn("public"); + when(spaceService.isSuperManager(anyString())).thenReturn(true); + when(spaceService.getSpaceById(any())).thenReturn(space); + when(spaceService.getSpaceByGroupId(anyString())).thenReturn(space); + + Identity identity = mock(Identity.class); + when(identity.getUserId()).thenReturn("john"); + NEWS_UTILS.when(() -> NewsUtils.getUserIdentity(anyString())).thenReturn(identity); + NEWS_UTILS.when(() -> NewsUtils.canPublishNews(anyString(), any(Identity.class))).thenReturn(false); + when(newsTargetingService.getTargetsByNewsId(anyString())).thenReturn(null); + + PageVersion pageVersion = mock(PageVersion.class); + when(noteService.getPublishedVersionByPageIdAndLang(1L, null)).thenReturn(pageVersion); + + when(existingPage.getAuthor()).thenReturn("john"); + when(pageVersion.getAuthor()).thenReturn("john"); + when(pageVersion.getUpdatedDate()).thenReturn(new Date()); + when(pageVersion.getAuthorFullName()).thenReturn("full name"); + // + assertThrows(IllegalAccessException.class, () -> newsService.deleteNews(existingPage.getId(), identity, false)); + + // when + when(spaceService.canRedactOnSpace(space, identity)).thenReturn(true); + when(noteService.deleteNote(existingPage.getWikiType(), existingPage.getWikiOwner(), existingPage.getName())).thenReturn(true); + DraftPage draftPage = mock(DraftPage.class); + when(draftPage.getId()).thenReturn("1"); + when(noteService.getLatestDraftOfPage(existingPage, identity.getUserId())).thenReturn(draftPage); + when(noteService.getDraftNoteById(anyString(), anyString())).thenReturn(draftPage); + + newsService.deleteNews(existingPage.getId(), identity, false); + + //Then + verify(noteService, times(1)).deleteNote(existingPage.getWikiType(), existingPage.getWikiOwner(), existingPage.getName()); + verify(noteService, times(1)).removeDraftById("1"); + verify(activityManager, times(1)).deleteActivity("1"); + } }