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