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