From 64b9238f15620249acdda8c1116cb9b5193f523e Mon Sep 17 00:00:00 2001 From: Ayoub Zayati Date: Sat, 28 Sep 2024 00:45:21 +0200 Subject: [PATCH] feat: Implement Space news target auto creation listener in order to create space news target when a space is created - EXO-73039 - Meeds-io/MIPs#129 (#241) --- .../SpaceNewsTargetAutoCreationListener.java | 64 +++++++++++++++++++ .../news/service/NewsTargetingService.java | 20 +++++- .../impl/NewsTargetingServiceImpl.java | 43 +++++++++---- .../webapp/WEB-INF/conf/configuration.xml | 1 + .../conf/news/feature-flags-configuration.xml | 35 ++++++++++ .../WEB-INF/conf/news/news-configuration.xml | 10 +++ 6 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 content-service/src/main/java/io/meeds/news/listener/SpaceNewsTargetAutoCreationListener.java create mode 100644 content-webapp/src/main/webapp/WEB-INF/conf/news/feature-flags-configuration.xml diff --git a/content-service/src/main/java/io/meeds/news/listener/SpaceNewsTargetAutoCreationListener.java b/content-service/src/main/java/io/meeds/news/listener/SpaceNewsTargetAutoCreationListener.java new file mode 100644 index 000000000..e869f3832 --- /dev/null +++ b/content-service/src/main/java/io/meeds/news/listener/SpaceNewsTargetAutoCreationListener.java @@ -0,0 +1,64 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.news.listener; + +import java.util.Map; + +import org.exoplatform.commons.utils.CommonsUtils; +import org.exoplatform.services.log.ExoLogger; +import org.exoplatform.services.log.Log; +import org.exoplatform.services.security.ConversationState; +import org.exoplatform.services.security.Identity; +import org.exoplatform.social.core.space.SpaceListenerPlugin; +import org.exoplatform.social.core.space.model.Space; +import org.exoplatform.social.core.space.spi.SpaceLifeCycleEvent; + +import io.meeds.news.rest.NewsTargetingEntity; +import io.meeds.news.service.NewsTargetingService; + +public class SpaceNewsTargetAutoCreationListener extends SpaceListenerPlugin { + + private static final Log LOG = + ExoLogger.getLogger(SpaceNewsTargetAutoCreationListener.class); + + private NewsTargetingService newsTargetingService; + + private static final String SPACE_NEWS_TARGET_AUTO_CREATION_FEATURE = "spaceNewsTargetAutoCreation"; + + public SpaceNewsTargetAutoCreationListener(NewsTargetingService newsTargetingService) { + this.newsTargetingService = newsTargetingService; + } + + @Override + public void spaceCreated(SpaceLifeCycleEvent event) { + if (CommonsUtils.isFeatureActive(SPACE_NEWS_TARGET_AUTO_CREATION_FEATURE)) { + Identity currentIdentity = ConversationState.getCurrent().getIdentity(); + Space space = event.getSpace(); + NewsTargetingEntity spaceNewsTargetEntity = new NewsTargetingEntity(); + spaceNewsTargetEntity.setName(space.getDisplayName()); + spaceNewsTargetEntity.setProperties(Map.of("label", space.getDisplayName(), "permissions", "space:" + space.getId())); + try { + newsTargetingService.createNewsTarget(spaceNewsTargetEntity, currentIdentity, false); + } catch (Exception e) { + LOG.warn("Can't create space {} news target", space.getPrettyName()); + } + } + } +} diff --git a/content-service/src/main/java/io/meeds/news/service/NewsTargetingService.java b/content-service/src/main/java/io/meeds/news/service/NewsTargetingService.java index 4406aed3d..9619bcdb2 100644 --- a/content-service/src/main/java/io/meeds/news/service/NewsTargetingService.java +++ b/content-service/src/main/java/io/meeds/news/service/NewsTargetingService.java @@ -63,8 +63,7 @@ void deleteTargetByName(String targetName, * Gets the {@link List} of {@link News} targets linked to a given * {@link News} * - * @param news {@link News} for which targets to be - * retrieved + * @param news {@link News} for which targets to be retrieved * @return {@link List} of {@link News} targets by {@link News} news object */ List getTargetsByNews(News news); @@ -127,6 +126,23 @@ Metadata createNewsTarget(NewsTargetingEntity newsTargetingEntity, org.exoplatform.services.security.Identity currentIdentity) throws IllegalArgumentException, IllegalAccessException; + /** + * Create news target + * + * @param newsTargetingEntity {@link News} TargetingEntity + * @param currentIdentity current {@link Identity} attempting to create + * {@link News} target + * @param checkPermissions true if permissions are checked + * @return created {@link News} target {@link Metadata} + * @throws IllegalArgumentException when user creates a {@link News} target + * that already exists + * @throws IllegalAccessException when user doesn't have access to create + * {@link News} target + */ + Metadata createNewsTarget(NewsTargetingEntity newsTargetingEntity, + org.exoplatform.services.security.Identity currentIdentity, + boolean checkPermissions) throws IllegalArgumentException, IllegalAccessException; + /** * Update news target * diff --git a/content-service/src/main/java/io/meeds/news/service/impl/NewsTargetingServiceImpl.java b/content-service/src/main/java/io/meeds/news/service/impl/NewsTargetingServiceImpl.java index afbdc33a7..ecd0a4eec 100644 --- a/content-service/src/main/java/io/meeds/news/service/impl/NewsTargetingServiceImpl.java +++ b/content-service/src/main/java/io/meeds/news/service/impl/NewsTargetingServiceImpl.java @@ -25,6 +25,9 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; @@ -48,9 +51,6 @@ import io.meeds.news.rest.NewsTargetingPermissionsEntity; import io.meeds.news.service.NewsTargetingService; import io.meeds.news.utils.NewsUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; /** * Service managing News Targeting @@ -118,7 +118,7 @@ public List getAllowedTargets(org.exoplatform.services.secu @Override public void deleteTargetByName(String targetName, org.exoplatform.services.security.Identity currentIdentity) throws IllegalAccessException { - if (currentIdentity != null && !NewsUtils.canManageNewsPublishTargets(currentIdentity)) { + if (!NewsUtils.canManageNewsPublishTargets(currentIdentity)) { throw new IllegalArgumentException("User " + currentIdentity.getUserId() + " not authorized to delete news target with name " + targetName); } @@ -129,7 +129,10 @@ public void deleteTargetByName(String targetName, @Override public List getTargetsByNews(News news) { - NewsTargetObject newsTargetObject = new NewsTargetObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, news.getId(), null, Long.parseLong(news.getSpaceId())); + NewsTargetObject newsTargetObject = new NewsTargetObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, + news.getId(), + null, + Long.parseLong(news.getSpaceId())); List newsTargets = metadataService.getMetadataItemsByMetadataTypeAndObject(METADATA_TYPE.getName(), newsTargetObject); return newsTargets.stream().map(MetadataItem::getMetadata).map(Metadata::getName).toList(); @@ -144,14 +147,21 @@ public void saveNewsTarget(News news, if (!NewsUtils.canPublishNews(news.getSpaceId(), currentIdentity)) { throw new IllegalAccessException("User " + currentUserId + " not authorized to save news targets"); } - NewsTargetObject newsTargetObject = new NewsTargetObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, news.getId(), null, Long.parseLong(news.getSpaceId())); + NewsTargetObject newsTargetObject = new NewsTargetObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, + news.getId(), + null, + Long.parseLong(news.getSpaceId())); Identity currentSocIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, currentUserId); Map properties = new LinkedHashMap<>(); properties.put(NewsUtils.DISPLAYED_STATUS, String.valueOf(displayed)); targets.stream().forEach(targetName -> { try { MetadataKey metadataKey = new MetadataKey(NewsTargetingService.METADATA_TYPE.getName(), targetName, 0); - metadataService.createMetadataItem(newsTargetObject, metadataKey, properties, Long.parseLong(currentSocIdentity.getId()), false); + metadataService.createMetadataItem(newsTargetObject, + metadataKey, + properties, + Long.parseLong(currentSocIdentity.getId()), + false); } catch (ObjectAlreadyExistsException e) { LOG.warn("Targets with name {} is already associated to object {}. Ignore error since it will not affect result.", targetName, @@ -174,7 +184,10 @@ public List getNewsTargetItemsByTargetName(String targetName, long @Override public void deleteNewsTargets(News news) { - NewsTargetObject newsTargetObject = new NewsTargetObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, news.getId(), null, Long.parseLong(news.getSpaceId())); + NewsTargetObject newsTargetObject = new NewsTargetObject(NewsUtils.NEWS_METADATA_OBJECT_TYPE, + news.getId(), + null, + Long.parseLong(news.getSpaceId())); metadataService.deleteMetadataItemsByMetadataTypeAndObject(METADATA_TYPE.getName(), newsTargetObject); } @@ -191,13 +204,21 @@ public void deleteNewsTargets(News news, String currentUserId) throws IllegalAcc public Metadata createNewsTarget(NewsTargetingEntity newsTargetingEntity, org.exoplatform.services.security.Identity currentIdentity) throws IllegalArgumentException, IllegalAccessException { + return createNewsTarget(newsTargetingEntity, currentIdentity, true); + } + + @Override + public Metadata createNewsTarget(NewsTargetingEntity newsTargetingEntity, + org.exoplatform.services.security.Identity currentIdentity, + boolean withPermissions) throws IllegalArgumentException, IllegalAccessException { + if (withPermissions && !NewsUtils.canManageNewsPublishTargets(currentIdentity)) { + throw new IllegalAccessException("User " + currentIdentity.getUserId() + " not authorized to create news targets"); + } Identity identity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, currentIdentity.getUserId()); long userIdentityId = identity == null ? 0 : Long.parseLong(identity.getId()); Metadata metadata = fromEntity(newsTargetingEntity); metadata.setCreatorId(userIdentityId); - if (!NewsUtils.canManageNewsPublishTargets(currentIdentity)) { - throw new IllegalAccessException("User " + currentIdentity.getUserId() + " not authorized to create news targets"); - } + MetadataKey targetMetadataKey = new MetadataKey(METADATA_TYPE.getName(), metadata.getName(), 0); Metadata storedMetadata = metadataService.getMetadataByKey(targetMetadataKey); if (storedMetadata != null) { diff --git a/content-webapp/src/main/webapp/WEB-INF/conf/configuration.xml b/content-webapp/src/main/webapp/WEB-INF/conf/configuration.xml index fb4a4bcd6..b19066d98 100644 --- a/content-webapp/src/main/webapp/WEB-INF/conf/configuration.xml +++ b/content-webapp/src/main/webapp/WEB-INF/conf/configuration.xml @@ -32,5 +32,6 @@ war:/conf/news/metadata-plugins-configuration.xml war:/conf/news/gamification-configuration.xml war:/conf/news/ckeditor-configuration.xml + war:/conf/news/feature-flags-configuration.xml diff --git a/content-webapp/src/main/webapp/WEB-INF/conf/news/feature-flags-configuration.xml b/content-webapp/src/main/webapp/WEB-INF/conf/news/feature-flags-configuration.xml new file mode 100644 index 000000000..902800a6e --- /dev/null +++ b/content-webapp/src/main/webapp/WEB-INF/conf/news/feature-flags-configuration.xml @@ -0,0 +1,35 @@ + + + + + ContentFeatureProperties + org.exoplatform.container.ExtendedPropertyConfigurator + + + ContentFeatureProperties + Content Feature enablement flag + + + + + \ No newline at end of file diff --git a/content-webapp/src/main/webapp/WEB-INF/conf/news/news-configuration.xml b/content-webapp/src/main/webapp/WEB-INF/conf/news/news-configuration.xml index e16eb920f..944405ee1 100644 --- a/content-webapp/src/main/webapp/WEB-INF/conf/news/news-configuration.xml +++ b/content-webapp/src/main/webapp/WEB-INF/conf/news/news-configuration.xml @@ -59,4 +59,14 @@ + + + org.exoplatform.social.core.space.spi.SpaceService + + content.listeners.social.space + addSpaceListener + io.meeds.news.listener.SpaceNewsTargetAutoCreationListener + Create a space news when a new space is created + +