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