001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.membershippolicy;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryUtil;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.interval.IntervalActionProcessor;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.security.membershippolicy.BaseSiteMembershipPolicy;
023    import com.liferay.portal.kernel.security.membershippolicy.MembershipPolicyException;
024    import com.liferay.portal.kernel.util.ListUtil;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.UnicodeProperties;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.GroupConstants;
029    import com.liferay.portal.model.User;
030    import com.liferay.portal.service.GroupLocalServiceUtil;
031    import com.liferay.portal.service.UserLocalServiceUtil;
032    import com.liferay.portlet.asset.model.AssetCategory;
033    import com.liferay.portlet.asset.model.AssetTag;
034    
035    import java.io.Serializable;
036    
037    import java.util.ArrayList;
038    import java.util.LinkedHashMap;
039    import java.util.List;
040    import java.util.Map;
041    
042    /**
043     * @author Sergio González
044     */
045    public class DefaultSiteMembershipPolicy extends BaseSiteMembershipPolicy {
046    
047            @Override
048            public void checkMembership(
049                            long[] userIds, long[] addGroupIds, long[] removeGroupIds)
050                    throws PortalException {
051    
052                    if (addGroupIds != null) {
053                            checkAddUsersLimitedGroup(userIds, addGroupIds);
054                    }
055            }
056    
057            @Override
058            public boolean isMembershipAllowed(long userId, long groupId) {
059                    try {
060                            Group group = GroupLocalServiceUtil.getGroup(groupId);
061    
062                            if (group.isLimitedToParentSiteMembers()) {
063                                    if (!GroupLocalServiceUtil.hasUserGroup(
064                                                    userId, group.getParentGroupId(), false)) {
065    
066                                            return false;
067                                    }
068                            }
069                    }
070                    catch (Exception e) {
071                            _log.error(e, e);
072                    }
073    
074                    return true;
075            }
076    
077            @Override
078            public void propagateMembership(
079                            long[] userIds, long[] addGroupIds, long[] removeGroupIds)
080                    throws PortalException {
081    
082                    if (removeGroupIds != null) {
083                            for (long removeGroupId : removeGroupIds) {
084                                    removeUsersFromLimitedChildrenGroups(userIds, removeGroupId);
085                            }
086                    }
087            }
088    
089            @Override
090            public void verifyPolicy(Group group) throws PortalException {
091                    if (group.isLimitedToParentSiteMembers()) {
092                            verifyLimitedParentMembership(group);
093                    }
094            }
095    
096            @Override
097            public void verifyPolicy(
098                            Group group, Group oldGroup, List<AssetCategory> oldAssetCategories,
099                            List<AssetTag> oldAssetTags,
100                            Map<String, Serializable> oldExpandoAttributes,
101                            UnicodeProperties oldTypeSettingsProperties)
102                    throws PortalException {
103    
104                    if (group.isLimitedToParentSiteMembers()) {
105                            if ((group.getParentGroupId() == oldGroup.getParentGroupId()) &&
106                                    oldGroup.isLimitedToParentSiteMembers()) {
107    
108                                    verifyPolicy(group);
109                            }
110                            else {
111                                    List<Group> childrenGroups = getLimitedChildrenGroups(group);
112    
113                                    for (Group childrenGroup : childrenGroups) {
114                                            verifyPolicy(childrenGroup);
115                                    }
116                            }
117                    }
118            }
119    
120            protected void checkAddUsersLimitedGroup(long[] userIds, long[] groupIds)
121                    throws PortalException {
122    
123                    MembershipPolicyException membershipPolicyException = null;
124    
125                    for (long groupId : groupIds) {
126                            Group group = GroupLocalServiceUtil.getGroup(groupId);
127    
128                            if (!group.isLimitedToParentSiteMembers()) {
129                                    continue;
130                            }
131    
132                            for (long userId : userIds) {
133                                    if (!GroupLocalServiceUtil.hasUserGroup(
134                                                    userId, group.getParentGroupId(), false)) {
135    
136                                            if (membershipPolicyException == null) {
137                                                    membershipPolicyException =
138                                                            new MembershipPolicyException(
139                                                                    MembershipPolicyException.
140                                                                            SITE_MEMBERSHIP_NOT_ALLOWED);
141                                            }
142    
143                                            User user = UserLocalServiceUtil.getUser(userId);
144    
145                                            membershipPolicyException.addUser(user);
146                                    }
147                            }
148    
149                            if (membershipPolicyException != null) {
150                                    membershipPolicyException.addGroup(group);
151                            }
152                    }
153    
154                    if (membershipPolicyException != null) {
155                            throw membershipPolicyException;
156                    }
157            }
158    
159            protected List<Group> getLimitedChildrenGroups(Group group)
160                    throws PortalException {
161    
162                    List<Group> parentGroups = new ArrayList<>();
163    
164                    parentGroups.add(group);
165    
166                    LinkedHashMap<String, Object> groupParams = new LinkedHashMap<>();
167    
168                    groupParams.put("groupsTree", parentGroups);
169                    groupParams.put(
170                            "membershipRestriction",
171                            GroupConstants.MEMBERSHIP_RESTRICTION_TO_PARENT_SITE_MEMBERS);
172                    groupParams.put("site", Boolean.TRUE);
173    
174                    List<Group> childrenGroups = GroupLocalServiceUtil.search(
175                            group.getCompanyId(), null, StringPool.BLANK, groupParams,
176                            QueryUtil.ALL_POS, QueryUtil.ALL_POS);
177    
178                    List<Group> filteredChildrenGroups = ListUtil.copy(childrenGroups);
179    
180                    for (Group childrenGroup : childrenGroups) {
181                            for (Group ancestorGroup : childrenGroup.getAncestors()) {
182                                    if ((ancestorGroup.getGroupId() != group.getGroupId()) &&
183                                            !ancestorGroup.isLimitedToParentSiteMembers()) {
184    
185                                            filteredChildrenGroups.remove(childrenGroup);
186    
187                                            break;
188                                    }
189                            }
190                    }
191    
192                    return filteredChildrenGroups;
193            }
194    
195            protected void removeUsersFromLimitedChildrenGroups(
196                            long[] userIds, long groupId)
197                    throws PortalException {
198    
199                    Group group = GroupLocalServiceUtil.getGroup(groupId);
200    
201                    List<Group> childrenGroups = getLimitedChildrenGroups(group);
202    
203                    for (Group childrenGroup : childrenGroups) {
204                            if (!childrenGroup.isLimitedToParentSiteMembers()) {
205                                    continue;
206                            }
207    
208                            for (long userId : userIds) {
209                                    UserLocalServiceUtil.unsetGroupUsers(
210                                            childrenGroup.getGroupId(), new long[] {userId}, null);
211                            }
212                    }
213            }
214    
215            protected void verifyLimitedParentMembership(final Group group)
216                    throws PortalException {
217    
218                    int total = UserLocalServiceUtil.getGroupUsersCount(group.getGroupId());
219    
220                    final IntervalActionProcessor<Void> intervalActionProcessor =
221                            new IntervalActionProcessor<>(total);
222    
223                    intervalActionProcessor.setPerformIntervalActionMethod(
224                            new IntervalActionProcessor.PerformIntervalActionMethod<Void>() {
225    
226                                    @Override
227                                    public Void performIntervalAction(int start, int end)
228                                            throws PortalException {
229    
230                                            List<User> users = UserLocalServiceUtil.getGroupUsers(
231                                                    group.getGroupId(), start, end);
232    
233                                            for (User user : users) {
234                                                    if (!UserLocalServiceUtil.hasGroupUser(
235                                                                    group.getParentGroupId(), user.getUserId())) {
236    
237                                                            UserLocalServiceUtil.unsetGroupUsers(
238                                                                    group.getGroupId(),
239                                                                    new long[] {user.getUserId()}, null);
240                                                    }
241                                                    else {
242                                                            intervalActionProcessor.incrementStart();
243                                                    }
244                                            }
245    
246                                            return null;
247                                    }
248    
249                            });
250    
251                    intervalActionProcessor.performIntervalActions();
252            }
253    
254            private static final Log _log = LogFactoryUtil.getLog(
255                    DefaultSiteMembershipPolicy.class);
256    
257    }