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