Skip to content

Commit

Permalink
fix : old published news images not displayed for non members - EXO-6…
Browse files Browse the repository at this point in the history
…4578


This change will update the permissions for displaying published news images to non-members.
  • Loading branch information
sofyenne authored Jun 9, 2023
1 parent 7e7ed5c commit 5c4dacd
Show file tree
Hide file tree
Showing 3 changed files with 291 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* Copyright (C) 2023 eXo Platform SAS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.exoplatform.news.upgrade.jcr;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;

import org.exoplatform.commons.upgrade.UpgradePluginExecutionContext;
import org.exoplatform.commons.upgrade.UpgradeProductPlugin;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ExtendedNode;
import org.exoplatform.services.jcr.ext.app.SessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.impl.core.query.QueryImpl;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;

public class PublishedNewsImagesPermissionsUpgradePlugin extends UpgradeProductPlugin {
public static final String EXO_PRIVILEGEABLE = "exo:privilegeable";

public static final String[] READ_PERMISSIONS = new String[] { "read" };

public static final String PLATFORM_USERS_GROUP_IDENTITY = "*:/platform/users";

private static final Log LOG =
ExoLogger.getLogger(PublishedNewsImagesPermissionsUpgradePlugin.class.getName());

private static final Pattern IMAGE_SRC_PATTERN = Pattern.compile("src=\"/portal/rest/images/?(.+)?\"");

private final RepositoryService repositoryService;

private final SessionProviderService sessionProviderService;

private int imageNewsUpdatedCount;

private int newsCount;

public PublishedNewsImagesPermissionsUpgradePlugin(InitParams initParams,
RepositoryService repositoryService,
SessionProviderService sessionProviderService) {
super(initParams);
this.repositoryService = repositoryService;
this.sessionProviderService = sessionProviderService;
}

@Override
public boolean shouldProceedToUpgrade(String newVersion,
String previousGroupVersion,
UpgradePluginExecutionContext previousUpgradePluginExecution) {
int executionCount = previousUpgradePluginExecution == null ? 0 : previousUpgradePluginExecution.getExecutionCount();
return !isExecuteOnlyOnce() || executionCount == 0;
}

@Override
public void processUpgrade(String s, String s1) {
long startupTime = System.currentTimeMillis();
LOG.info("Start upgrade of published news images permission");
SessionProvider sessionProvider = null;
try {
sessionProvider = sessionProviderService.getSystemSessionProvider(null);
Session session = sessionProvider.getSession(
repositoryService.getCurrentRepository()
.getConfiguration()
.getDefaultWorkspaceName(),
repositoryService.getCurrentRepository());
QueryManager qm = session.getWorkspace().getQueryManager();
int limit = 10, offset = 0;
String stringQuery =
"select * from exo:news WHERE publication:currentState = 'published' AND jcr:path LIKE '/Groups/spaces/%'";
Query jcrQuery = qm.createQuery(stringQuery, Query.SQL);
boolean hasMoreElements = true;
while (hasMoreElements) {
((QueryImpl) jcrQuery).setOffset(offset);
((QueryImpl) jcrQuery).setLimit(limit);
NodeIterator nodeIterator = jcrQuery.execute().getNodes();
if (nodeIterator != null) {
while (nodeIterator.hasNext()) {
Node newsNode = nodeIterator.nextNode();
updateNewsImagesPermissions(newsNode, session);
}
if (nodeIterator.getSize() < limit) {
// no more elements
hasMoreElements = false;
} else {
offset += limit;
}
}
}
LOG.info("End updating of '{}' images for '{}' published news . It took {} ms.",
this.imageNewsUpdatedCount,
this.newsCount,
(System.currentTimeMillis() - startupTime));
} catch (Exception e) {
LOG.error("An error occurred when upgrading published images news permissions :", e);
} finally {
if (sessionProvider != null) {
sessionProvider.close();
}
}
}

private void updateNewsImagesPermissions(Node newsNode, Session session) throws RepositoryException {
Matcher matcher = IMAGE_SRC_PATTERN.matcher(getStringProperty(newsNode, "exo:body"));
int imagesCount = 0;
while (matcher.find()) {
String match = matcher.group(1);
String imageUUID = match.substring(match.lastIndexOf("/") + 1);
ExtendedNode image = (ExtendedNode) session.getNodeByUUID(imageUUID);
if (image != null) {
if (image.canAddMixin(EXO_PRIVILEGEABLE)) {
image.addMixin(EXO_PRIVILEGEABLE);
}
boolean isPublicImage = image.getACL()
.getPermissionEntries()
.stream()
.filter(accessControlEntry -> accessControlEntry.getIdentity()
.equals(PLATFORM_USERS_GROUP_IDENTITY))
.toList()
.size() > 0;
if (!isPublicImage) {
// make news images public
image.setPermission(PLATFORM_USERS_GROUP_IDENTITY, READ_PERMISSIONS);
image.save();
imagesCount += 1;
}
}
}
if (imagesCount > 0) {
this.newsCount += 1;
this.imageNewsUpdatedCount += imagesCount;
}
}

private String getStringProperty(Node node, String propertyName) throws RepositoryException {
if (node.hasProperty(propertyName)) {
return node.getProperty(propertyName).getString();
}
return "";
}
}
34 changes: 34 additions & 0 deletions data-upgrade-news/src/main/resources/conf/portal/configuration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,40 @@
</value-param>
</init-params>
</component-plugin>

<component-plugin>
<name>PublishedNewsImagesPermissionsUpgradePlugin</name>
<set-method>addUpgradePlugin</set-method>
<type>org.exoplatform.news.upgrade.jcr.PublishedNewsImagesPermissionsUpgradePlugin</type>
<description>Update published news images permissions</description>
<init-params>
<value-param>
<name>product.group.id</name>
<description>The groupId of the product</description>
<value>org.exoplatform.news</value>
</value-param>
<value-param>
<name>plugin.execution.order</name>
<description>The plugin execution order</description>
<value>2</value>
</value-param>
<value-param>
<name>plugin.upgrade.execute.once</name>
<description>Execute this upgrade plugin only once</description>
<value>true</value>
</value-param>
<value-param>
<name>plugin.upgrade.async.execution</name>
<description>The plugin will be executed in an asynchronous mode</description>
<value>true</value>
</value-param>
<value-param>
<name>plugin.upgrade.target.version</name>
<description>Target version of the plugin</description>
<value>6.4.2</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>

</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package org.exoplatform.news.upgrade.jcr;

import static org.exoplatform.news.upgrade.jcr.PublishedNewsImagesPermissionsUpgradePlugin.EXO_PRIVILEGEABLE;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

import java.util.ArrayList;

import javax.jcr.*;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.ValueParam;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.access.AccessControlList;
import org.exoplatform.services.jcr.config.RepositoryEntry;
import org.exoplatform.services.jcr.core.ExtendedNode;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.app.SessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.impl.core.query.QueryImpl;

@RunWith(MockitoJUnitRunner.class)
public class PublishedNewsImagesPermissionsUpgradePluginTest {

@Mock
RepositoryService repositoryService;

@Mock
ManageableRepository repository;

@Mock
RepositoryEntry repositoryEntry;

@Mock
Session session;

@Mock
SessionProviderService sessionProviderService;

@Mock
SessionProvider sessionProvider;

@Test
public void publishedNewsImagesPermissionsUpgradePluginTest() throws Exception {
InitParams initParams = new InitParams();
ValueParam valueParam = new ValueParam();
valueParam.setName("product.group.id");
valueParam.setValue("org.exoplatform.news");

when(sessionProviderService.getSystemSessionProvider(any())).thenReturn(sessionProvider);
when(repositoryService.getCurrentRepository()).thenReturn(repository);
when(repository.getConfiguration()).thenReturn(repositoryEntry);
when(sessionProvider.getSession(any(), any())).thenReturn(session);
QueryManager qm = mock(QueryManager.class);
Workspace workSpace = mock(Workspace.class);
when(session.getWorkspace()).thenReturn(workSpace);
when(workSpace.getQueryManager()).thenReturn(qm);
Query query = mock(QueryImpl.class);
when(qm.createQuery(anyString(), anyString())).thenReturn(query);
QueryResult queryResult = mock(QueryResult.class);
when(query.execute()).thenReturn(queryResult);
NodeIterator nodeIterator = mock(NodeIterator.class);
when(queryResult.getNodes()).thenReturn(nodeIterator);
when(nodeIterator.hasNext()).thenReturn(true, false);
Node newsNode = mock(Node.class);
Property property = mock(Property.class);
when(nodeIterator.nextNode()).thenReturn(newsNode);
when(newsNode.hasProperty("exo:body")).thenReturn(true);
when(newsNode.getProperty("exo:body")).thenReturn(property);
when(property.getString()).thenReturn("news body with image src=\"/portal/rest/images/repository/collaboration/123\"");
ExtendedNode imageNode = mock(ExtendedNode.class);
when(session.getNodeByUUID("123")).thenReturn(imageNode);
when(imageNode.canAddMixin(EXO_PRIVILEGEABLE)).thenReturn(true);
AccessControlList accessControlList = mock(AccessControlList.class);
when(imageNode.getACL()).thenReturn(accessControlList);
when(accessControlList.getPermissionEntries()).thenReturn(new ArrayList<>());
// when
PublishedNewsImagesPermissionsUpgradePlugin publishedNewsImagesPermissionsUpgradePlugin =
new PublishedNewsImagesPermissionsUpgradePlugin(initParams,
repositoryService,
sessionProviderService);
publishedNewsImagesPermissionsUpgradePlugin.processUpgrade(null, null);
// then
verify(imageNode, times(1)).setPermission("*:/platform/users", new String[] { "read" });
verify(imageNode, times(1)).save();
}
}

0 comments on commit 5c4dacd

Please sign in to comment.