Skip to content

Commit b9291e2

Browse files
authored
fix/issue-#2800: Fix bug with favorites getting deleted when a favorited portlet gets deleted and a user subequently favorites another portlet or unfavorites a portlet (#2801)
1 parent 3fc79c9 commit b9291e2

File tree

5 files changed

+380
-45
lines changed

5 files changed

+380
-45
lines changed

uPortal-api/uPortal-api-internal/src/main/java/org/apereo/portal/portlets/favorites/FavoritesUtils.java

+4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ public class FavoritesUtils {
5454

5555
private Logger logger = LoggerFactory.getLogger(getClass());
5656

57+
public void setPortletDefinitionRegistry(IPortletDefinitionRegistry registry) {
58+
this.portletRegistry = registry;
59+
}
60+
5761
/**
5862
* Get the favorite collections of portlets (i.e. suitable folders ("tabs") in the user layout.)
5963
* Suitable layout nodes are of type folder with @type attribute favorite_collection.

uPortal-api/uPortal-api-rest/src/main/java/org/apereo/portal/layout/dlm/remoting/UpdatePreferencesServlet.java

+84-20
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apereo.portal.layout.IUserLayoutManager;
4040
import org.apereo.portal.layout.IUserLayoutStore;
4141
import org.apereo.portal.layout.PortletSubscribeIdResolver;
42+
import org.apereo.portal.layout.dlm.MissingPortletDefinition;
4243
import org.apereo.portal.layout.dlm.UserPrefsHandler;
4344
import org.apereo.portal.layout.node.IUserLayoutChannelDescription;
4445
import org.apereo.portal.layout.node.IUserLayoutFolderDescription;
@@ -51,13 +52,14 @@
5152
import org.apereo.portal.portlet.registry.IPortletWindowRegistry;
5253
import org.apereo.portal.portlets.favorites.FavoritesUtils;
5354
import org.apereo.portal.security.IAuthorizationPrincipal;
55+
import org.apereo.portal.security.IAuthorizationService;
5456
import org.apereo.portal.security.IPermission;
5557
import org.apereo.portal.security.IPerson;
5658
import org.apereo.portal.security.PermissionHelper;
57-
import org.apereo.portal.services.AuthorizationServiceFacade;
5859
import org.apereo.portal.services.GroupService;
5960
import org.apereo.portal.user.IUserInstance;
6061
import org.apereo.portal.user.IUserInstanceManager;
62+
import org.apereo.portal.utils.personalize.IPersonalizer;
6163
import org.slf4j.Logger;
6264
import org.slf4j.LoggerFactory;
6365
import org.springframework.beans.factory.annotation.Autowired;
@@ -86,6 +88,7 @@ public class UpdatePreferencesServlet {
8688

8789
protected final Logger logger = LoggerFactory.getLogger(getClass());
8890

91+
private IAuthorizationService authorizationService;
8992
private IPortletDefinitionRegistry portletDefinitionRegistry;
9093
private IUserIdentityStore userIdentityStore;
9194
private IUserInstanceManager userInstanceManager;
@@ -94,6 +97,7 @@ public class UpdatePreferencesServlet {
9497
private MessageSource messageSource;
9598
private IPortletWindowRegistry portletWindowRegistry;
9699
private FavoritesUtils favoritesUtils;
100+
private IPersonalizer personalizer;
97101

98102
@Value("${org.apereo.portal.layout.dlm.remoting.addedWindowState:null}")
99103
private String addedPortletWindowState;
@@ -109,6 +113,11 @@ private void initAddedPortletWindowState() {
109113
}
110114
}
111115

116+
@Autowired
117+
public void setAuthorizationService(IAuthorizationService authorizationService) {
118+
this.authorizationService = authorizationService;
119+
}
120+
112121
@Autowired
113122
public void setUserLayoutStore(IUserLayoutStore userLayoutStore) {
114123
this.userLayoutStore = userLayoutStore;
@@ -150,6 +159,11 @@ public void setFavoritesUtils(FavoritesUtils favoritesUtils) {
150159
this.favoritesUtils = favoritesUtils;
151160
}
152161

162+
@Autowired
163+
public void setPersonalizer(IPersonalizer personalizer) {
164+
this.personalizer = personalizer;
165+
}
166+
153167
/** Default name given to newly created tabs. */
154168
protected static final String DEFAULT_TAB_NAME = "New Tab"; // TODO: Requires i18n!
155169

@@ -606,13 +620,15 @@ public ModelAndView addFavorite(
606620
final IUserLayoutManager ulm = upm.getUserLayoutManager();
607621

608622
final IUserLayoutChannelDescription channel =
609-
new UserLayoutChannelDescription(person, pdef, request.getSession());
623+
new UserLayoutChannelDescription(person, pdef, request.getSession(), personalizer);
610624

611625
// get favorite tab
612626
final String favoriteTabNodeId = favoritesUtils.getFavoriteTabNodeId(ulm.getUserLayout());
613627

614628
if (favoriteTabNodeId != null) {
615-
// add portlet to favorite tab
629+
removeOrphanedFavoritesFromLayout(ulm);
630+
631+
// add new favorite portlet to favorite tab
616632
final IUserLayoutNodeDescription node = addNodeToTab(ulm, channel, favoriteTabNodeId);
617633

618634
if (node == null) {
@@ -696,12 +712,13 @@ public ModelAndView removeFavorite(
696712

697713
String resp = new String();
698714

715+
removeOrphanedFavoritesFromLayout(ulm, favoritePortlets);
716+
717+
boolean saveNeeded = false;
699718
for (IUserLayoutChannelDescription deleteNode : favoritesToDelete) {
700-
if (deleteNode != null && deleteNode instanceof UserLayoutChannelDescription) {
701-
UserLayoutChannelDescription channelDescription =
702-
(UserLayoutChannelDescription) deleteNode;
719+
if (deleteNode != null) {
703720
try {
704-
if (!ulm.deleteNode(channelDescription.getChannelSubscribeId())) {
721+
if (!ulm.deleteNode(deleteNode.getChannelSubscribeId())) {
705722

706723
logger.warn(
707724
"Error deleting the node {} from favorites for user {}",
@@ -718,27 +735,30 @@ public ModelAndView removeFavorite(
718735
"Can''t remove favorite",
719736
locale);
720737
} else {
738+
saveNeeded = true;
721739
// load success message
722-
723-
resp =
724-
getMessage(
725-
"success.remove.portlet",
726-
"Removed from Favorites successfully",
727-
locale);
728740
}
729-
// save the user's layout
741+
} catch (PortalException e) {
742+
return handlePersistError(request, response, e);
743+
}
744+
}
745+
if (saveNeeded) {
746+
try {
730747
ulm.saveUserLayout();
731748
} catch (PortalException e) {
732749
return handlePersistError(request, response, e);
733750
}
751+
resp =
752+
getMessage(
753+
"success.remove.portlet",
754+
"Removed from Favorites successfully",
755+
locale);
734756
}
735757
}
736758

737759
return new ModelAndView("jsonView", Collections.singletonMap("response", resp));
738760
}
739761

740-
// save the user's layout
741-
ulm.saveUserLayout();
742762
return new ModelAndView(
743763
"jsonView",
744764
Collections.singletonMap(
@@ -789,7 +809,7 @@ else if (fname != null)
789809

790810
IUserLayoutChannelDescription channel =
791811
new UserLayoutChannelDescription(
792-
getPerson(ui, response), definition, request.getSession());
812+
getPerson(ui, response), definition, request.getSession(), personalizer);
793813

794814
IUserLayoutNodeDescription node;
795815
if (isTab(ulm, destinationId)) {
@@ -1453,13 +1473,12 @@ protected String getMessage(String key, String argument, String defaultMessage,
14531473
}
14541474

14551475
private IAuthorizationPrincipal getUserPrincipal(final String userName) {
1456-
final IEntity user = GroupService.getEntity(userName, IPerson.class);
1476+
final IEntity user = this.personEntityService.getPersonEntity(userName);
14571477
if (user == null) {
14581478
return null;
14591479
}
14601480

1461-
final AuthorizationServiceFacade authService = AuthorizationServiceFacade.instance();
1462-
return authService.newPrincipal(user);
1481+
return authorizationService.newPrincipal(user);
14631482
}
14641483

14651484
private String getTabIdFromName(IUserLayout userLayout, String tabName) {
@@ -1595,4 +1614,49 @@ private boolean attemptNodeMove(
15951614
private boolean isFolder(IUserLayoutManager ulm, String id) {
15961615
return ulm.getNode(id).getType().equals(IUserLayoutNodeDescription.LayoutNodeType.FOLDER);
15971616
}
1617+
1618+
private void removeOrphanedFavoritesFromLayout(IUserLayoutManager ulm) {
1619+
List<IUserLayoutNodeDescription> favoritesPortlets =
1620+
favoritesUtils.getFavoritePortletLayoutNodes(ulm.getUserLayout());
1621+
removeOrphanedFavoritesFromLayout(ulm, favoritesPortlets);
1622+
}
1623+
1624+
private void removeOrphanedFavoritesFromLayout(
1625+
IUserLayoutManager ulm, List<IUserLayoutNodeDescription> favoritesPortlets) {
1626+
// remove orphaned favorites (meaning they are favorites for portlets that have been
1627+
// removed/deleted) ...keep in mind that ulm.saveLayout() will need to be called
1628+
// in order to actually save the changes to the layout
1629+
for (IUserLayoutNodeDescription node : favoritesPortlets) {
1630+
if (node instanceof IUserLayoutChannelDescription) {
1631+
IUserLayoutChannelDescription channelDescription =
1632+
(IUserLayoutChannelDescription) node;
1633+
if (channelDescription
1634+
.getChannelPublishId()
1635+
.equals(MissingPortletDefinition.CHANNEL_ID)) {
1636+
ulm.deleteNode(channelDescription.getChannelSubscribeId());
1637+
}
1638+
}
1639+
}
1640+
}
1641+
1642+
// for unit testing begin
1643+
1644+
public interface IPersonEntityService {
1645+
IEntity getPersonEntity(String userName);
1646+
}
1647+
1648+
public class GroupServiceBasedPersonEntityService implements IPersonEntityService {
1649+
@Override
1650+
public IEntity getPersonEntity(String userName) {
1651+
return GroupService.getEntity(userName, IPerson.class);
1652+
}
1653+
}
1654+
1655+
private IPersonEntityService personEntityService = new GroupServiceBasedPersonEntityService();
1656+
1657+
public void setPersonEntityService(IPersonEntityService personEntityService) {
1658+
this.personEntityService = personEntityService;
1659+
}
1660+
1661+
// for unit testing end
15981662
}

0 commit comments

Comments
 (0)