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