diff --git a/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java b/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java
index e2d40f2705..cf8375a7bc 100644
--- a/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java
+++ b/source/java/org/alfresco/repo/activities/feed/FeedNotifierImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2013 Alfresco Software Limited.
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -331,7 +331,7 @@ public class FeedNotifierImpl implements FeedNotifier, ApplicationContextAware
try
{
- final String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
+ final String currentUser = AuthenticationUtil.getRunAsUser();
final String tenantDomain = TenantUtil.getCurrentDomain();
// process the feeds using the batch processor {@link BatchProcessor}
@@ -346,11 +346,12 @@ public class FeedNotifierImpl implements FeedNotifier, ApplicationContextAware
public void beforeProcess() throws Throwable
{
- AuthenticationUtil.setRunAsUser(currentUser);
+ AuthenticationUtil.setFullyAuthenticatedUser(currentUser);
}
public void afterProcess() throws Throwable
{
+ AuthenticationUtil.clearCurrentSecurityContext();
}
public void process(final PersonInfo person) throws Throwable
diff --git a/source/test-java/org/alfresco/Repository01TestSuite.java b/source/test-java/org/alfresco/Repository01TestSuite.java
index e590c3b988..c408f53ddb 100644
--- a/source/test-java/org/alfresco/Repository01TestSuite.java
+++ b/source/test-java/org/alfresco/Repository01TestSuite.java
@@ -86,6 +86,7 @@ public class Repository01TestSuite extends TestSuite
{
suite.addTestSuite(org.alfresco.repo.activities.ActivityServiceImplTest.class);
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.activities.feed.FeedNotifierTest.class));
+ suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.activities.feed.FeedNotifierJobTest.class));
suite.addTestSuite(org.alfresco.repo.admin.RepoAdminServiceImplTest.class);
suite.addTestSuite(org.alfresco.repo.admin.patch.PatchTest.class);
suite.addTestSuite(org.alfresco.repo.admin.registry.RegistryServiceImplTest.class);
diff --git a/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierJobTest.java b/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierJobTest.java
new file mode 100644
index 0000000000..1338801ea9
--- /dev/null
+++ b/source/test-java/org/alfresco/repo/activities/feed/FeedNotifierJobTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+package org.alfresco.repo.activities.feed;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.activities.post.lookup.PostLookup;
+import org.alfresco.repo.domain.activities.ActivityPostDAO;
+import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
+import org.alfresco.repo.security.authentication.AuthenticationContext;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
+import org.alfresco.repo.tenant.TenantAdminService;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.service.cmr.action.ActionService;
+import org.alfresco.service.cmr.activities.ActivityService;
+import org.alfresco.service.cmr.admin.RepoAdminService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.PersonService;
+import org.alfresco.service.cmr.site.SiteService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.ApplicationContextHelper;
+import org.alfresco.util.GUID;
+import org.alfresco.util.Pair;
+import org.alfresco.util.PropertyMap;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Tests for the {@link FeedNotifierJob} class.
+ *
+ * @author alex.mukha
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class FeedNotifierJobTest
+{
+ private static ApplicationContext ctx = null;
+
+ private FeedNotifierJob feedNotifierJob;
+ private @Mock JobExecutionContext jobCtx;
+ private TenantAdminService tenantAdminService;
+ private TransactionService transactionService;
+ private FeedNotifierImpl feedNotifier;
+ private JobDetail jobDetail;
+ private ActivityService activityService;
+ private PersonService personService;
+ private FeedGenerator feedGenerator;
+ private PostLookup postLookup;
+ private ActivityPostDAO postDAO;
+ private RegisterErrorUserFeedNotifier userNotifier;
+ private NodeService nodeService;
+ private NamespaceService namespaceService;
+ private SiteService siteService;
+ private RepoAdminService repoAdminService;
+ private ActionService actionService;
+ private AuthenticationContext authenticationContext;
+
+ private NodeRef failingPersonNodeRef;
+ private NodeRef personNodeRef;
+ private String userName1 = "user1." + GUID.generate();
+ private String userName2 = "user2." + GUID.generate();
+
+ @BeforeClass
+ public static void init()
+ {
+ ApplicationContextHelper.setUseLazyLoading(false);
+ ApplicationContextHelper.setNoAutoStart(true);
+
+ ctx = ApplicationContextHelper.getApplicationContext();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() throws Exception
+ {
+ ChildApplicationContextFactory activitiesFeed = (ChildApplicationContextFactory) ctx.getBean("ActivitiesFeed");
+ ApplicationContext activitiesFeedCtx = activitiesFeed.getApplicationContext();
+ feedNotifier = (FeedNotifierImpl) activitiesFeedCtx.getBean("feedNotifier");
+ activityService = (ActivityService) activitiesFeedCtx.getBean("activityService");
+ feedGenerator = (FeedGenerator) activitiesFeedCtx.getBean("feedGenerator");
+ postLookup = (PostLookup) activitiesFeedCtx.getBean("postLookup");
+ ObjectFactory feedModelBuilderFactory = (ObjectFactory) activitiesFeedCtx.getBean("feedModelBuilderFactory");
+ EmailUserNotifier emailUserNotifier = (EmailUserNotifier) activitiesFeedCtx.getBean("emailUserNotifier");
+
+ tenantAdminService = (TenantAdminService) ctx.getBean("tenantAdminService");
+ transactionService = (TransactionService) ctx.getBean("transactionService");
+ personService = (PersonService) ctx.getBean("personService");
+ postDAO = (ActivityPostDAO) ctx.getBean("postDAO");
+ nodeService = (NodeService) ctx.getBean("nodeService");
+ namespaceService = (NamespaceService) ctx.getBean("namespaceService");
+ siteService = (SiteService) ctx.getBean("siteService");
+ repoAdminService = (RepoAdminService) ctx.getBean("repoAdminService");
+ actionService = (ActionService) ctx.getBean("ActionService");
+ authenticationContext = (AuthenticationContext) ctx.getBean("authenticationContext");
+
+ AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
+ // create some users
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+ {
+ @SuppressWarnings("synthetic-access")
+ public Void execute() throws Throwable
+ {
+ personNodeRef = createUser(userName1);
+ failingPersonNodeRef = createUser(userName2);
+ return null;
+ }
+ }, false, true);
+
+ // use our own user notifier for testing purposes
+ userNotifier = new RegisterErrorUserFeedNotifier();
+ userNotifier.setNodeService(nodeService);
+ userNotifier.setNamespaceService(namespaceService);
+ userNotifier.setSiteService(siteService);
+ userNotifier.setActivityService(activityService);
+ userNotifier.setRepoAdminService(repoAdminService);
+ userNotifier.setActionService(actionService);
+ userNotifier.setActivitiesFeedModdelBuilderFactory(feedModelBuilderFactory);
+ userNotifier.setAuthenticationContext(authenticationContext);
+ userNotifier.setExcludedEmailSuffixes(emailUserNotifier.getExcludedEmailSuffixes());
+
+ feedNotifier.setUserNotifier(userNotifier);
+
+ jobDetail = new JobDetail("feedNotifier", FeedNotifierJob.class);
+ JobDataMap jobDataMap = jobDetail.getJobDataMap();
+ jobDataMap.put("tenantAdminService", tenantAdminService);
+ jobDataMap.put("feedNotifier", feedNotifier);
+ feedNotifierJob = new FeedNotifierJob();
+
+ when(jobCtx.getJobDetail()).thenReturn(jobDetail);
+ }
+
+ private NodeRef createUser(String userName)
+ {
+ PropertyMap personProps = new PropertyMap();
+ personProps.put(ContentModel.PROP_USERNAME, userName);
+ personProps.put(ContentModel.PROP_FIRSTNAME, userName);
+ personProps.put(ContentModel.PROP_LASTNAME, userName);
+ personProps.put(ContentModel.PROP_EMAIL, userName + "@email.com");
+ return personService.createPerson(personProps);
+ }
+
+ private void generateActivities() throws Exception
+ {
+ // generate the activities
+ postLookup.execute();
+
+ Long maxSequence = postDAO.getMaxActivitySeq();
+ while (maxSequence != null)
+ {
+ feedGenerator.execute();
+
+ maxSequence = postDAO.getMaxActivitySeq();
+ }
+ }
+
+ @After
+ public void cleanUp()
+ {
+ AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+ {
+ @SuppressWarnings("synthetic-access")
+ public Void execute() throws Throwable
+ {
+ personService.deletePerson(failingPersonNodeRef);
+ personService.deletePerson(personNodeRef);
+ return null;
+ }
+ }, false, true);
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
+
+ /**
+ * Test for MNT-12398
+ * @throws JobExecutionException
+ */
+ @Test
+ public void testAuthentication() throws Exception
+ {
+ final String activityType = "org.alfresco.profile.status-changed";
+ final String siteId = null;
+ final String appTool = "profile";
+ // Status update
+ final String jsonActivityData = "{\"status\":\"test\"}";
+
+ // and activity for userName2
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+ {
+ @SuppressWarnings("synthetic-access")
+ public Void execute() throws Throwable
+ {
+ AuthenticationUtil.pushAuthentication();
+ AuthenticationUtil.setFullyAuthenticatedUser(userName1);
+
+ activityService.postActivity(activityType, siteId, appTool, jsonActivityData);
+
+ AuthenticationUtil.popAuthentication();
+
+ return null;
+ }
+ }, false, true);
+
+ generateActivities();
+ // Start feed notifier as user2 (the generation should be run as system internally)
+ // We should not get the "Unable to get user feed entries for 'user1' - currently logged in as 'user2'"
+ AuthenticationUtil.setFullyAuthenticatedUser(userName2);
+ feedNotifierJob.execute(jobCtx);
+
+ assertNull("The notification failed with error " + userNotifier.getError(), userNotifier.getError());
+ }
+
+ private class RegisterErrorUserFeedNotifier extends EmailUserNotifier
+ {
+ private Exception error = null;
+
+ public Exception getError()
+ {
+ return error;
+ }
+
+ @Override
+ public Pair notifyUser(final NodeRef personNodeRef, String subject, Object[] subjectParams, Map siteNames,
+ String shareUrl, int repeatIntervalMins, String templateNodeRef)
+ {
+ try
+ {
+ return super.notifyUser(personNodeRef, subject, subjectParams, siteNames, shareUrl, repeatIntervalMins, templateNodeRef);
+ }
+ catch (AccessDeniedException e)
+ {
+ error = e;
+ throw e;
+ }
+ }
+
+ }
+
+}