001    /**
002     * Copyright (c) 2000-2012 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.service.permission;
016    
017    import com.liferay.portal.NoSuchResourceException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.util.Validator;
021    import com.liferay.portal.model.Group;
022    import com.liferay.portal.model.Layout;
023    import com.liferay.portal.model.LayoutConstants;
024    import com.liferay.portal.model.Organization;
025    import com.liferay.portal.model.ResourceConstants;
026    import com.liferay.portal.model.ResourcePermission;
027    import com.liferay.portal.model.User;
028    import com.liferay.portal.model.impl.VirtualLayout;
029    import com.liferay.portal.security.auth.PrincipalException;
030    import com.liferay.portal.security.permission.ActionKeys;
031    import com.liferay.portal.security.permission.PermissionChecker;
032    import com.liferay.portal.service.GroupLocalServiceUtil;
033    import com.liferay.portal.service.LayoutLocalServiceUtil;
034    import com.liferay.portal.service.OrganizationLocalServiceUtil;
035    import com.liferay.portal.service.ResourceLocalServiceUtil;
036    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
037    import com.liferay.portal.service.UserLocalServiceUtil;
038    import com.liferay.portal.util.PropsValues;
039    import com.liferay.portlet.sites.util.SitesUtil;
040    
041    import java.util.List;
042    
043    /**
044     * @author Charles May
045     * @author Brian Wing Shun Chan
046     * @author Raymond Augé
047     */
048    public class LayoutPermissionImpl implements LayoutPermission {
049    
050            public void check(
051                            PermissionChecker permissionChecker, Layout layout, String actionId)
052                    throws PortalException, SystemException {
053    
054                    if (!contains(permissionChecker, layout, actionId)) {
055                            throw new PrincipalException();
056                    }
057            }
058    
059            public void check(
060                            PermissionChecker permissionChecker, long groupId,
061                            boolean privateLayout, long layoutId, String actionId)
062                    throws PortalException, SystemException {
063    
064                    if (!contains(
065                                    permissionChecker, groupId, privateLayout, layoutId,
066                                    actionId)) {
067    
068                            throw new PrincipalException();
069                    }
070            }
071    
072            public void check(
073                            PermissionChecker permissionChecker, long plid, String actionId)
074                    throws PortalException, SystemException {
075    
076                    if (!contains(permissionChecker, plid, actionId)) {
077                            throw new PrincipalException();
078                    }
079            }
080    
081            public boolean contains(
082                            PermissionChecker permissionChecker, Layout layout,
083                            boolean checkViewableGroup, String actionId)
084                    throws PortalException, SystemException {
085    
086                    return contains(
087                            permissionChecker, layout, null, checkViewableGroup, actionId);
088            }
089    
090            public boolean contains(
091                            PermissionChecker permissionChecker, Layout layout, String actionId)
092                    throws PortalException, SystemException {
093    
094                    return contains(permissionChecker, layout, null, actionId);
095            }
096    
097            public boolean contains(
098                            PermissionChecker permissionChecker, Layout layout,
099                            String controlPanelCategory, boolean checkViewableGroup,
100                            String actionId)
101                    throws PortalException, SystemException {
102    
103                    return containsWithViewableGroup(
104                            permissionChecker, layout, controlPanelCategory, checkViewableGroup,
105                            actionId);
106            }
107    
108            public boolean contains(
109                            PermissionChecker permissionChecker, Layout layout,
110                            String controlPanelCategory, String actionId)
111                    throws PortalException, SystemException {
112    
113                    return contains(
114                            permissionChecker, layout, controlPanelCategory, false, actionId);
115            }
116    
117            public boolean contains(
118                            PermissionChecker permissionChecker, long groupId,
119                            boolean privateLayout, long layoutId, String actionId)
120                    throws PortalException, SystemException {
121    
122                    return contains(
123                            permissionChecker, groupId, privateLayout, layoutId, null,
124                            actionId);
125            }
126    
127            public boolean contains(
128                            PermissionChecker permissionChecker, long groupId,
129                            boolean privateLayout, long layoutId, String controlPanelCategory,
130                            String actionId)
131                    throws PortalException, SystemException {
132    
133                    Layout layout = LayoutLocalServiceUtil.getLayout(
134                            groupId, privateLayout, layoutId);
135    
136                    if (isAttemptToModifyLockedLayout(layout, actionId)) {
137                            return false;
138                    }
139    
140                    return contains(
141                            permissionChecker, layout, controlPanelCategory, actionId);
142            }
143    
144            public boolean contains(
145                            PermissionChecker permissionChecker, long plid, String actionId)
146                    throws PortalException, SystemException {
147    
148                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
149    
150                    return contains(permissionChecker, layout, actionId);
151            }
152    
153            public boolean containsWithoutViewableGroup(
154                            PermissionChecker permissionChecker, Layout layout,
155                            String controlPanelCategory, boolean checkLayoutUpdateable,
156                            String actionId)
157                    throws PortalException, SystemException {
158    
159                    if (checkLayoutUpdateable &&
160                            !actionId.equals(ActionKeys.CUSTOMIZE) &&
161                            !actionId.equals(ActionKeys.VIEW) &&
162                            (layout instanceof VirtualLayout)) {
163    
164                            return false;
165                    }
166    
167                    if (actionId.equals(ActionKeys.CUSTOMIZE) &&
168                            (layout instanceof VirtualLayout)) {
169    
170                            VirtualLayout virtualLayout = (VirtualLayout)layout;
171    
172                            layout = virtualLayout.getWrappedModel();
173                    }
174    
175                    if (actionId.equals(ActionKeys.DELETE) &&
176                            !SitesUtil.isLayoutDeleteable(layout)) {
177    
178                            return false;
179                    }
180    
181                    Group group = layout.getGroup();
182    
183                    if (checkLayoutUpdateable && !group.isLayoutSetPrototype() &&
184                            isAttemptToModifyLockedLayout(layout, actionId)) {
185    
186                            return false;
187                    }
188    
189                    User user = UserLocalServiceUtil.getUserById(
190                            permissionChecker.getUserId());
191    
192                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
193                            !user.isDefaultUser() && !group.isUser()) {
194    
195                            // This is new way of doing an ownership check without having to
196                            // have a userId field on the model. When the instance model was
197                            // first created, we set the user's userId as the ownerId of the
198                            // individual scope ResourcePermission of the Owner Role.
199                            // Therefore, ownership can be determined by obtaining the Owner
200                            // role ResourcePermission for the current instance model and
201                            // testing it with the hasOwnerPermission call.
202    
203                            ResourcePermission resourcePermission =
204                                    ResourcePermissionLocalServiceUtil.getResourcePermission(
205                                            layout.getCompanyId(), Layout.class.getName(),
206                                            ResourceConstants.SCOPE_INDIVIDUAL,
207                                            String.valueOf(layout.getPlid()),
208                                            permissionChecker.getOwnerRoleId());
209    
210                            if (permissionChecker.hasOwnerPermission(
211                                            layout.getCompanyId(), Layout.class.getName(),
212                                            String.valueOf(layout.getPlid()),
213                                            resourcePermission.getOwnerId(), actionId)) {
214    
215                                    return true;
216                            }
217                    }
218    
219                    if (GroupPermissionUtil.contains(
220                                    permissionChecker, layout.getGroupId(),
221                                    ActionKeys.MANAGE_LAYOUTS)) {
222    
223                            return true;
224                    }
225                    else if (actionId.equals(ActionKeys.ADD_LAYOUT) &&
226                                     GroupPermissionUtil.contains(
227                                             permissionChecker, layout.getGroupId(),
228                                             ActionKeys.ADD_LAYOUT)) {
229    
230                            return true;
231                    }
232    
233                    if (PropsValues.PERMISSIONS_VIEW_DYNAMIC_INHERITANCE &&
234                            !actionId.equals(ActionKeys.VIEW)) {
235    
236                            // Check upward recursively to see if any pages above grant the
237                            // action
238    
239                            long parentLayoutId = layout.getParentLayoutId();
240    
241                            while (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
242                                    Layout parentLayout = LayoutLocalServiceUtil.getLayout(
243                                            layout.getGroupId(), layout.isPrivateLayout(),
244                                            parentLayoutId);
245    
246                                    if (contains(
247                                                    permissionChecker, parentLayout, controlPanelCategory,
248                                                    actionId)) {
249    
250                                            return true;
251                                    }
252    
253                                    parentLayoutId = parentLayout.getParentLayoutId();
254                            }
255                    }
256    
257                    try {
258                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
259                                    if (ResourcePermissionLocalServiceUtil.
260                                                    getResourcePermissionsCount(
261                                                            layout.getCompanyId(), Layout.class.getName(),
262                                                            ResourceConstants.SCOPE_INDIVIDUAL,
263                                                            String.valueOf(layout.getPlid())) == 0) {
264    
265                                            throw new NoSuchResourceException();
266                                    }
267                            }
268                            else {
269                                    ResourceLocalServiceUtil.getResource(
270                                            layout.getCompanyId(), Layout.class.getName(),
271                                            ResourceConstants.SCOPE_INDIVIDUAL,
272                                            String.valueOf(layout.getPlid()));
273                            }
274                    }
275                    catch (NoSuchResourceException nsre) {
276                            boolean addGroupPermission = true;
277                            boolean addGuestPermission = true;
278    
279                            if (layout.isPrivateLayout()) {
280                                    addGuestPermission = false;
281                            }
282    
283                            ResourceLocalServiceUtil.addResources(
284                                    layout.getCompanyId(), layout.getGroupId(), 0,
285                                    Layout.class.getName(), layout.getPlid(), false,
286                                    addGroupPermission, addGuestPermission);
287                    }
288    
289                    return permissionChecker.hasPermission(
290                            layout.getGroupId(), Layout.class.getName(), layout.getPlid(),
291                            actionId);
292            }
293    
294            public boolean containsWithoutViewableGroup(
295                            PermissionChecker permissionChecker, Layout layout,
296                            String controlPanelCategory, String actionId)
297                    throws PortalException, SystemException {
298    
299                    return containsWithoutViewableGroup(
300                            permissionChecker, layout, controlPanelCategory, true, actionId);
301            }
302    
303            protected boolean containsWithViewableGroup(
304                            PermissionChecker permissionChecker, Layout layout,
305                            String controlPanelCategory, boolean checkViewableGroup,
306                            String actionId)
307                    throws PortalException, SystemException {
308    
309                    if (actionId.equals(ActionKeys.VIEW) && checkViewableGroup) {
310                            return isViewableGroup(
311                                    permissionChecker, layout, controlPanelCategory,
312                                    checkViewableGroup);
313                    }
314    
315                    return containsWithoutViewableGroup(
316                            permissionChecker, layout, controlPanelCategory, actionId);
317            }
318    
319            protected boolean isAttemptToModifyLockedLayout(
320                    Layout layout, String actionId) {
321    
322                    if (!SitesUtil.isLayoutUpdateable(layout) &&
323                            (ActionKeys.CUSTOMIZE.equals(actionId) ||
324                             ActionKeys.UPDATE.equals(actionId))) {
325    
326                            return true;
327                    }
328    
329                    return false;
330            }
331    
332            protected boolean isViewableGroup(
333                            PermissionChecker permissionChecker, Layout layout,
334                            String controlPanelCategory, boolean checkResourcePermission)
335                    throws PortalException, SystemException {
336    
337                    Group group = GroupLocalServiceUtil.getGroup(layout.getGroupId());
338    
339                    // Inactive sites are not viewable
340    
341                    if (!group.isActive()) {
342                            return false;
343                    }
344                    else if (group.isStagingGroup()) {
345                            Group liveGroup = group.getLiveGroup();
346    
347                            if (!liveGroup.isActive()) {
348                                    return false;
349                            }
350                    }
351    
352                    // User private layouts are only viewable by the user and anyone who can
353                    // update the user. The user must also be active.
354    
355                    if (group.isUser()) {
356                            long groupUserId = group.getClassPK();
357    
358                            if (groupUserId == permissionChecker.getUserId()) {
359                                    return true;
360                            }
361    
362                            User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
363    
364                            if (!groupUser.isActive()) {
365                                    return false;
366                            }
367    
368                            if (layout.isPrivateLayout()) {
369                                    if (GroupPermissionUtil.contains(
370                                                    permissionChecker, groupUser.getGroupId(),
371                                                    ActionKeys.MANAGE_LAYOUTS) ||
372                                            UserPermissionUtil.contains(
373                                                    permissionChecker, groupUserId,
374                                                    groupUser.getOrganizationIds(), ActionKeys.UPDATE)) {
375    
376                                            return true;
377                                    }
378    
379                                    return false;
380                            }
381                    }
382    
383                    // If the current group is staging, only users with editorial rights
384                    // can access it
385    
386                    if (group.isStagingGroup()) {
387                            if (GroupPermissionUtil.contains(
388                                            permissionChecker, group.getGroupId(),
389                                            ActionKeys.VIEW_STAGING)) {
390    
391                                    return true;
392                            }
393    
394                            return false;
395                    }
396    
397                    // Control panel layouts are only viewable by authenticated users
398    
399                    if (group.isControlPanel()) {
400                            if (!permissionChecker.isSignedIn()) {
401                                    return false;
402                            }
403    
404                            if (PortalPermissionUtil.contains(
405                                            permissionChecker, ActionKeys.VIEW_CONTROL_PANEL)) {
406    
407                                    return true;
408                            }
409    
410                            if (Validator.isNotNull(controlPanelCategory)) {
411                                    return true;
412                            }
413    
414                            return false;
415                    }
416    
417                    // Site layouts are only viewable by users who are members of the site
418                    // or by users who can update the site
419    
420                    if (group.isSite()) {
421                            if (GroupPermissionUtil.contains(
422                                            permissionChecker, group.getGroupId(),
423                                            ActionKeys.MANAGE_LAYOUTS) ||
424                                     GroupPermissionUtil.contains(
425                                            permissionChecker, group.getGroupId(), ActionKeys.UPDATE)) {
426    
427                                    return true;
428                            }
429    
430                            if (layout.isPrivateLayout() &&
431                                    !permissionChecker.isGroupMember(group.getGroupId())) {
432    
433                                    return false;
434                            }
435                    }
436    
437                    // Organization site layouts are also viewable by users who belong to
438                    // the organization or by users who can update organization
439    
440                    if (group.isCompany()) {
441                            return false;
442                    }
443                    else if (group.isLayoutPrototype()) {
444                            if (LayoutPrototypePermissionUtil.contains(
445                                            permissionChecker, group.getClassPK(), ActionKeys.VIEW)) {
446    
447                                    return true;
448                            }
449    
450                            return false;
451                    }
452                    else if (group.isLayoutSetPrototype()) {
453                            if (LayoutSetPrototypePermissionUtil.contains(
454                                            permissionChecker, group.getClassPK(), ActionKeys.VIEW)) {
455    
456                                    return true;
457                            }
458    
459                            return false;
460                    }
461                    else if (group.isOrganization()) {
462                            long organizationId = group.getOrganizationId();
463    
464                            if (OrganizationLocalServiceUtil.hasUserOrganization(
465                                            permissionChecker.getUserId(), organizationId, false,
466                                            false)) {
467    
468                                    return true;
469                            }
470                            else if (OrganizationPermissionUtil.contains(
471                                                    permissionChecker, organizationId, ActionKeys.UPDATE)) {
472    
473                                    return true;
474                            }
475    
476                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
477                                    List<Organization> userOrgs =
478                                            OrganizationLocalServiceUtil.getUserOrganizations(
479                                                    permissionChecker.getUserId());
480    
481                                    for (Organization organization : userOrgs) {
482                                            for (Organization ancestorOrganization :
483                                                            organization.getAncestors()) {
484    
485                                                    if (organizationId ==
486                                                                    ancestorOrganization.getOrganizationId()) {
487    
488                                                            return true;
489                                                    }
490                                            }
491                                    }
492                            }
493                    }
494                    else if (group.isUserGroup()) {
495                            if (UserGroupPermissionUtil.contains(
496                                            permissionChecker, group.getClassPK(), ActionKeys.UPDATE)) {
497    
498                                    return true;
499                            }
500                    }
501    
502                    // Only check the actual Layout if all of the above failed
503    
504                    if (containsWithoutViewableGroup(
505                                    permissionChecker, layout, controlPanelCategory,
506                                    ActionKeys.VIEW)) {
507    
508                            return true;
509                    }
510    
511                    // As a last resort, check if any top level pages are viewable by the
512                    // user
513    
514                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
515                            layout.getGroupId(), layout.isPrivateLayout(),
516                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
517    
518                    for (Layout curLayout : layouts) {
519                            if (!curLayout.isHidden() &&
520                                    containsWithoutViewableGroup(
521                                            permissionChecker, curLayout, controlPanelCategory,
522                                            ActionKeys.VIEW)) {
523    
524                                    return true;
525                            }
526                    }
527    
528                    return false;
529            }
530    
531    }