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 96f877c46..536826c84 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 @@ -111,6 +111,8 @@ public class News { private boolean canPublish; + private boolean canSchedule; + private List sharedInSpacesList; private String url; diff --git a/content-service/src/main/java/io/meeds/news/rest/NewsRest.java b/content-service/src/main/java/io/meeds/news/rest/NewsRest.java index 7640cf48b..0dcc3ab89 100644 --- a/content-service/src/main/java/io/meeds/news/rest/NewsRest.java +++ b/content-service/src/main/java/io/meeds/news/rest/NewsRest.java @@ -712,7 +712,9 @@ public ResponseEntity> search(@Parameter(descriptio @ApiResponse(responseCode = "401", description = "User not authorized to schedule a news"), @ApiResponse(responseCode = "404", description = "Space not found"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public ResponseEntity canScheduleNews(@PathVariable("spaceId") String spaceId) { + public ResponseEntity canScheduleNews(@PathVariable("spaceId") String spaceId, + @Parameter(description = "target article id") + @RequestParam("articleId") String articleId) { org.exoplatform.services.security.Identity currentIdentity = ConversationState.getCurrent().getIdentity(); try { if (StringUtils.isBlank(spaceId)) { @@ -722,8 +724,12 @@ public ResponseEntity canScheduleNews(@PathVariable("spaceId") String s if (space == null) { return ResponseEntity.notFound().build(); } + News news = newsService.getNewsArticleById(articleId); + if (news == null) { + return ResponseEntity.notFound().build(); + } - return ResponseEntity.ok(newsService.canScheduleNews(space, currentIdentity)); + return ResponseEntity.ok(newsService.canScheduleNews(space, currentIdentity, news)); } catch (Exception e) { LOG.error("Error when checking if the authenticated user can schedule a news", e); return ResponseEntity.internalServerError().build(); diff --git a/content-service/src/main/java/io/meeds/news/service/NewsService.java b/content-service/src/main/java/io/meeds/news/service/NewsService.java index fabbcd17e..e504eb05b 100644 --- a/content-service/src/main/java/io/meeds/news/service/NewsService.java +++ b/content-service/src/main/java/io/meeds/news/service/NewsService.java @@ -285,11 +285,12 @@ News scheduleNews(News news, /** * Checks if the user can schedule publishinga News * - * @param space - * @param currentIdentity + * @param space target space + * @param currentIdentity current user identity + * @param article target article * @return boolean : true if the user can schedule publishing a News */ - boolean canScheduleNews(Space space, org.exoplatform.services.security.Identity currentIdentity); + boolean canScheduleNews(Space space, org.exoplatform.services.security.Identity currentIdentity, News article); /** * Checks if the user can view the News 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 a6a0556db..134ce5786 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 @@ -511,6 +511,10 @@ public News getNewsByIdAndLang(String newsId, news.setCanEdit(canEditNews(news, currentIdentity.getUserId())); news.setCanDelete(canDeleteNews(currentIdentity, news)); news.setCanPublish(NewsUtils.canPublishNews(news.getSpaceId(), currentIdentity)); + Space space = spaceService.getSpaceById(news.getSpaceId()); + if (space != null) { + news.setCanSchedule(canScheduleNews(space, currentIdentity, news)); + } news.setTargets(newsTargetingService.getTargetsByNews(news)); ExoSocialActivity activity = null; try { @@ -573,6 +577,10 @@ public List getNews(NewsFilter filter, Identity currentIdentity) throws Ex news.setCanEdit(canEditNews(news, currentIdentity.getUserId())); news.setCanDelete(canDeleteNews(currentIdentity, news)); news.setCanPublish(NewsUtils.canPublishNews(news.getSpaceId(), currentIdentity)); + Space space = spaceService.getSpaceById(news.getSpaceId()); + if (space != null) { + news.setCanSchedule(canScheduleNews(space, currentIdentity, news)); + } }); return newsList; } @@ -733,7 +741,7 @@ public News getNewsByActivityIdAndLang(String activityId, Identity currentIdenti @Override public News scheduleNews(News news, Identity currentIdentity, String newsObjectType) throws Exception { Space space = news.getSpaceId() == null ? null : spaceService.getSpaceById(news.getSpaceId()); - if (!canScheduleNews(space, currentIdentity)) { + if (!canScheduleNews(space, currentIdentity, news)) { throw new IllegalArgumentException("User " + currentIdentity.getUserId() + " is not authorized to schedule news"); } if (newsObjectType.equalsIgnoreCase(NewsObjectType.DRAFT.name())) { @@ -787,8 +795,10 @@ public List search(org.exoplatform.social.core.identity.mode * {@inheritDoc} */ @Override - public boolean canScheduleNews(Space space, Identity currentIdentity) { - return spaceService.isManager(space, currentIdentity.getUserId()) + public boolean canScheduleNews(Space space, Identity currentIdentity, News article) { + boolean isArticleAuthor = article.getAuthor() != null && article.getAuthor().equals(currentIdentity.getUserId()); + boolean spaceMemberCanSchedule = isArticleAuthor && spaceService.isMember(space, currentIdentity.getUserId()); + return spaceMemberCanSchedule || spaceService.isManager(space, currentIdentity.getUserId()) || spaceService.isRedactor(space, currentIdentity.getUserId()) || NewsUtils.canPublishNews(space.getId(), currentIdentity); } @@ -817,7 +827,7 @@ public boolean canViewNews(News news, String authenticatedUser) { return false; } if (StringUtils.equals(news.getPublicationState(), STAGED) - && !canScheduleNews(space, NewsUtils.getUserIdentity(authenticatedUser))) { + && !canScheduleNews(space, NewsUtils.getUserIdentity(authenticatedUser), news)) { return false; } } catch (Exception e) { diff --git a/content-webapp/src/main/webapp/vue-app/news-activity-composer-app/components/ContentRichEditor.vue b/content-webapp/src/main/webapp/vue-app/news-activity-composer-app/components/ContentRichEditor.vue index d87034577..3dfedf787 100644 --- a/content-webapp/src/main/webapp/vue-app/news-activity-composer-app/components/ContentRichEditor.vue +++ b/content-webapp/src/main/webapp/vue-app/news-activity-composer-app/components/ContentRichEditor.vue @@ -44,7 +44,8 @@ :editor-icon="editorIcon" :publication-params="{ spaceId: spaceId, - canPublish: canScheduleArticle, + canPublish: canPublishArticle, + canSchedule: true, allowedTargets: allowedTargets }" :images-download-folder="'DRIVE_ROOT_NODE/News/images'" @@ -120,6 +121,7 @@ export default { editorTitleInputRef: 'articleTitle', imagesURLs: new Map(), canScheduleArticle: false, + canPublishArticle: false, postKey: 1, editorIcon: 'fas fa-newspaper', articleId: null, @@ -686,9 +688,12 @@ export default { } this.loading = false; }); - this.$newsServices.canScheduleNews(this.currentSpace.id).then(canScheduleArticle => { + this.$newsServices.canScheduleNews(this.currentSpace.id, this.article?.id).then(canScheduleArticle => { this.canScheduleArticle = canScheduleArticle; }); + this.$newsServices.canPublishNews(this.currentSpace.id).then(canPublishArticle => { + this.canPublishArticle = canPublishArticle; + }); }); }, fillArticle(articleId, setData, lang) { diff --git a/content-webapp/src/main/webapp/vue-app/news-details-app/components/ExoNewsDetailsApp.vue b/content-webapp/src/main/webapp/vue-app/news-details-app/components/ExoNewsDetailsApp.vue index ad006bec1..85b6c1eee 100644 --- a/content-webapp/src/main/webapp/vue-app/news-details-app/components/ExoNewsDetailsApp.vue +++ b/content-webapp/src/main/webapp/vue-app/news-details-app/components/ExoNewsDetailsApp.vue @@ -84,7 +84,7 @@ export default { if (resp !== null && resp !== UNAUTHORIZED_CODE) { this.news = resp; this.showEditButton = this.news.canEdit; - this.showPublishButton = this.news.canPublish; + this.showPublishButton = this.news.canPublish || this.news?.canSchedule; this.showDeleteButton = this.news.canDelete; if (this.news.lang) { this.addParamToUrl('lang', this.news.lang); diff --git a/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetails.vue b/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetails.vue index cb76ece07..a0d4ba59e 100644 --- a/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetails.vue +++ b/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetails.vue @@ -67,7 +67,8 @@ :params="{ spaceId: spaceId, allowedTargets: allowedTargets, - canPublish: news?.canPublish + canPublish: news?.canPublish, + canSchedule: news?.canSchedule }" :edit-mode="true" @publish="publishArticle" /> @@ -87,7 +88,9 @@ export default { news: { type: Object, required: false, - default: function() { return new Object(); } + default: () => { + return {}; + } }, newsId: { type: String, @@ -200,7 +203,7 @@ export default { } }, getSpaceById(spaceId) { - this.$spaceService.getSpaceById(spaceId, 'identity') + return this.$spaceService.getSpaceById(spaceId, 'identity') .then((space) => { if (space && space.identity && space.identity.id) { this.currentSpace = space; diff --git a/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetailsActivity.vue b/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetailsActivity.vue index 5d0329fd3..34bf06b4d 100644 --- a/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetailsActivity.vue +++ b/content-webapp/src/main/webapp/vue-app/news-details/components/ExoNewsDetailsActivity.vue @@ -71,13 +71,13 @@ export default { return this.sharedTemplateParams && this.sharedTemplateParams.newsId; }, showDeleteButton() { - return this.news && this.news.canDelete; + return this.news?.canDelete; }, showEditButton() { - return this.news && this.news.canEdit; + return this.news?.canEdit; }, showPublishButton() { - return this.news && this.news.canPublish; + return this.news?.canPublish || this.news?.canSchedule; }, }, created() { diff --git a/content-webapp/src/main/webapp/vue-app/news-details/main.js b/content-webapp/src/main/webapp/vue-app/news-details/main.js index 046b27bc8..ac8fb7447 100644 --- a/content-webapp/src/main/webapp/vue-app/news-details/main.js +++ b/content-webapp/src/main/webapp/vue-app/news-details/main.js @@ -54,7 +54,7 @@ export function init(params) { activityId: params.activityId, newsType: params.newsType, showEditButton: params.news.canEdit, - showPublishButton: params.news.canPublish, + showPublishButton: params.news.canPublish || params.news?.canSchedule, showCopyLinkButton: true, showDeleteButton: params.news.canDelete, }; diff --git a/content-webapp/src/main/webapp/vue-app/services/newsServices.js b/content-webapp/src/main/webapp/vue-app/services/newsServices.js index 4dea4d5f4..051755fc7 100644 --- a/content-webapp/src/main/webapp/vue-app/services/newsServices.js +++ b/content-webapp/src/main/webapp/vue-app/services/newsServices.js @@ -219,8 +219,8 @@ export function canUserCreateNews(spaceId) { }).then((resp) => resp && resp.ok && resp.json()); } -export function canScheduleNews(spaceId) { - return fetch(`${newsConstants.CONTENT_API}/contents/canScheduleNews/${eXo.env.portal.spaceId || spaceId}`, { +export function canScheduleNews(spaceId, articleId) { + return fetch(`${newsConstants.CONTENT_API}/contents/canScheduleNews/${eXo.env.portal.spaceId || spaceId}?articleId=${articleId}`, { headers: { 'Content-Type': 'application/json' },