001    /**
002     * Copyright (c) 2000-2011 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.VIEW) &&
159                            (layout instanceof VirtualLayout)) {
160    
161                            return false;
162                    }
163    
164                    if ((layout.isPrivateLayout() &&
165                             !PropsValues.LAYOUT_USER_PRIVATE_LAYOUTS_MODIFIABLE) ||
166                            (layout.isPublicLayout() &&
167                             !PropsValues.LAYOUT_USER_PUBLIC_LAYOUTS_MODIFIABLE)) {
168    
169                            if (actionId.equals(ActionKeys.UPDATE)) {
170                                    Group group = GroupLocalServiceUtil.getGroup(
171                                            layout.getGroupId());
172    
173                                    if (group.isUser()) {
174                                            return false;
175                                    }
176                            }
177                    }
178    
179                    Group group = layout.getGroup();
180    
181                    if (!group.isLayoutSetPrototype() &&
182                            isAttemptToModifyLockedLayout(layout, actionId)) {
183    
184                            return false;
185                    }
186    
187                    User user = UserLocalServiceUtil.getUserById(
188                            permissionChecker.getUserId());
189    
190                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
191                            !user.isDefaultUser() && !group.isUser()) {
192    
193                            // This is new way of doing an ownership check without having to
194                            // have a userId field on the model. When the instance model was
195                            // first created, we set the user's userId as the ownerId of the
196                            // individual scope ResourcePermission of the Owner Role.
197                            // Therefore, ownership can be determined by obtaining the Owner
198                            // role ResourcePermission for the current instance model and
199                            // testing it with the hasOwnerPermission call.
200    
201                            ResourcePermission resourcePermission =
202                                    ResourcePermissionLocalServiceUtil.getResourcePermission(
203                                            layout.getCompanyId(), Layout.class.getName(),
204                                            ResourceConstants.SCOPE_INDIVIDUAL,
205                                            String.valueOf(layout.getPlid()),
206                                            permissionChecker.getOwnerRoleId());
207    
208                            if (permissionChecker.hasOwnerPermission(
209                                            layout.getCompanyId(), Layout.class.getName(),
210                                            String.valueOf(layout.getPlid()),
211                                            resourcePermission.getOwnerId(), actionId)) {
212    
213                                    return true;
214                            }
215                    }
216    
217                    if (GroupPermissionUtil.contains(
218                                    permissionChecker, layout.getGroupId(),
219                                    ActionKeys.MANAGE_LAYOUTS)) {
220    
221                            return true;
222                    }
223                    else if (actionId.equals(ActionKeys.ADD_LAYOUT) &&
224                                     GroupPermissionUtil.contains(
225                                             permissionChecker, layout.getGroupId(),
226                                             ActionKeys.ADD_LAYOUT)) {
227    
228                            return true;
229                    }
230    
231                    if (PropsValues.PERMISSIONS_VIEW_DYNAMIC_INHERITANCE &&
232                            !actionId.equals(ActionKeys.VIEW)) {
233    
234                            // Check upward recursively to see if any pages above grant the
235                            // action
236    
237                            long parentLayoutId = layout.getParentLayoutId();
238    
239                            while (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
240                                    Layout parentLayout = LayoutLocalServiceUtil.getLayout(
241                                            layout.getGroupId(), layout.isPrivateLayout(),
242                                            layout.getParentLayoutId());
243    
244                                    if (contains(
245                                                    permissionChecker, parentLayout, controlPanelCategory,
246                                                    actionId)) {
247    
248                                            return true;
249                                    }
250    
251                                    parentLayoutId = parentLayout.getParentLayoutId();
252                            }
253                    }
254    
255                    try {
256                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
257                                    if (ResourcePermissionLocalServiceUtil.
258                                                    getResourcePermissionsCount(
259                                                            layout.getCompanyId(), Layout.class.getName(),
260                                                            ResourceConstants.SCOPE_INDIVIDUAL,
261                                                            String.valueOf(layout.getPlid())) == 0) {
262    
263                                            throw new NoSuchResourceException();
264                                    }
265                            }
266                            else {
267                                    ResourceLocalServiceUtil.getResource(
268                                            layout.getCompanyId(), Layout.class.getName(),
269                                            ResourceConstants.SCOPE_INDIVIDUAL,
270                                            String.valueOf(layout.getPlid()));
271                            }
272                    }
273                    catch (NoSuchResourceException nsre) {
274                            boolean addGroupPermission = true;
275                            boolean addGuestPermission = true;
276    
277                            if (layout.isPrivateLayout()) {
278                                    addGuestPermission = false;
279                            }
280    
281                            ResourceLocalServiceUtil.addResources(
282                                    layout.getCompanyId(), layout.getGroupId(), 0,
283                                    Layout.class.getName(), layout.getPlid(), false,
284                                    addGroupPermission, addGuestPermission);
285                    }
286    
287                    return permissionChecker.hasPermission(
288                            layout.getGroupId(), Layout.class.getName(), layout.getPlid(),
289                            actionId);
290            }
291    
292            protected boolean containsWithViewableGroup(
293                            PermissionChecker permissionChecker, Layout layout,
294                            String controlPanelCategory, boolean checkViewableGroup,
295                            String actionId)
296                    throws PortalException, SystemException {
297    
298                    if (actionId.equals(ActionKeys.VIEW) && checkViewableGroup) {
299                            return isViewableGroup(
300                                    permissionChecker, layout, controlPanelCategory,
301                                    checkViewableGroup);
302                    }
303    
304                    return containsWithoutViewableGroup(
305                            permissionChecker, layout, controlPanelCategory, actionId);
306            }
307    
308            protected boolean isAttemptToModifyLockedLayout(
309                    Layout layout, String actionId) {
310    
311                    if (!SitesUtil.isLayoutUpdateable(layout) &&
312                            (ActionKeys.CUSTOMIZE.equals(actionId) ||
313                             ActionKeys.UPDATE.equals(actionId))) {
314    
315                            return true;
316                    }
317    
318                    return false;
319            }
320    
321            protected boolean isViewableGroup(
322                            PermissionChecker permissionChecker, Layout layout,
323                            String controlPanelCategory, boolean checkResourcePermission)
324                    throws PortalException, SystemException {
325    
326                    Group group = GroupLocalServiceUtil.getGroup(layout.getGroupId());
327    
328                    // Inactive sites are not viewable
329    
330                    if (!group.isActive()) {
331                            return false;
332                    }
333                    else if (group.isStagingGroup()) {
334                            Group liveGroup = group.getLiveGroup();
335    
336                            if (!liveGroup.isActive()) {
337                                    return false;
338                            }
339                    }
340    
341                    // User private layouts are only viewable by the user and anyone who can
342                    // update the user. The user must also be active.
343    
344                    if (group.isUser()) {
345                            long groupUserId = group.getClassPK();
346    
347                            if (groupUserId == permissionChecker.getUserId()) {
348                                    return true;
349                            }
350    
351                            User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
352    
353                            if (!groupUser.isActive()) {
354                                    return false;
355                            }
356    
357                            if (layout.isPrivateLayout()) {
358                                    if (UserPermissionUtil.contains(
359                                                    permissionChecker, groupUserId,
360                                                    groupUser.getOrganizationIds(),
361                                                    ActionKeys.MANAGE_LAYOUTS) ||
362                                            UserPermissionUtil.contains(
363                                                    permissionChecker, groupUserId,
364                                                    groupUser.getOrganizationIds(), ActionKeys.UPDATE)) {
365    
366                                            return true;
367                                    }
368    
369                                    return false;
370                            }
371                    }
372    
373                    // If the current group is staging, only users with editorial rights
374                    // can access it
375    
376                    if (group.isStagingGroup()) {
377                            if (GroupPermissionUtil.contains(
378                                            permissionChecker, group.getGroupId(),
379                                            ActionKeys.VIEW_STAGING)) {
380    
381                                    return true;
382                            }
383    
384                            return false;
385                    }
386    
387                    // Control panel layouts are only viewable by authenticated users
388    
389                    if (group.isControlPanel()) {
390                            if (PortalPermissionUtil.contains(
391                                            permissionChecker, ActionKeys.VIEW_CONTROL_PANEL)) {
392    
393                                    return true;
394                            }
395    
396                            if (Validator.isNotNull(controlPanelCategory)) {
397                                    return true;
398                            }
399    
400                            return false;
401                    }
402    
403                    // Site layouts are only viewable by users who are members of the site
404                    // or by users who can update the site
405    
406                    if (group.isSite()) {
407                            if (GroupPermissionUtil.contains(
408                                            permissionChecker, group.getGroupId(),
409                                            ActionKeys.MANAGE_LAYOUTS) ||
410                                     GroupPermissionUtil.contains(
411                                            permissionChecker, group.getGroupId(),
412                                            ActionKeys.UPDATE)) {
413    
414                                    return true;
415                            }
416                    }
417    
418                    // Organization site layouts are also viewable by users who belong to
419                    // the organization or by users who can update organization
420    
421                    if (group.isCompany()) {
422                            return false;
423                    }
424                    else if (group.isLayoutPrototype()) {
425                            if (LayoutPrototypePermissionUtil.contains(
426                                            permissionChecker, group.getClassPK(), ActionKeys.VIEW)) {
427    
428                                    return true;
429                            }
430    
431                            return false;
432                    }
433                    else if (group.isLayoutSetPrototype()) {
434                            if (LayoutSetPrototypePermissionUtil.contains(
435                                            permissionChecker, group.getClassPK(), ActionKeys.VIEW)) {
436    
437                                    return true;
438                            }
439    
440                            return false;
441                    }
442                    else if (group.isOrganization()) {
443                            long organizationId = group.getOrganizationId();
444    
445                            if (OrganizationLocalServiceUtil.hasUserOrganization(
446                                            permissionChecker.getUserId(), organizationId, false,
447                                            false)) {
448    
449                                    return true;
450                            }
451                            else if (OrganizationPermissionUtil.contains(
452                                                    permissionChecker, organizationId, ActionKeys.UPDATE)) {
453    
454                                    return true;
455                            }
456    
457                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
458                                    List<Organization> userOrgs =
459                                            OrganizationLocalServiceUtil.getUserOrganizations(
460                                                    permissionChecker.getUserId());
461    
462                                    for (Organization organization : userOrgs) {
463                                            for (Organization ancestorOrganization :
464                                                            organization.getAncestors()) {
465    
466                                                    if (organizationId ==
467                                                                    ancestorOrganization.getOrganizationId()) {
468    
469                                                            return true;
470                                                    }
471                                            }
472                                    }
473                            }
474                    }
475                    else if (group.isUserGroup()) {
476                            if (UserGroupPermissionUtil.contains(
477                                            permissionChecker, group.getClassPK(), ActionKeys.UPDATE)) {
478    
479                                    return true;
480                            }
481                    }
482    
483                    // Only check the actual Layout if all of the above failed
484    
485                    if (containsWithoutViewableGroup(
486                                    permissionChecker, layout, controlPanelCategory,
487                                    ActionKeys.VIEW)) {
488    
489                            return true;
490                    }
491    
492                    // As a last resort, check if any top level pages are viewable by the
493                    // user
494    
495                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
496                            layout.getGroupId(), layout.isPrivateLayout(),
497                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
498    
499                    for (Layout curLayout : layouts) {
500                            if (!curLayout.isHidden() &&
501                                    containsWithoutViewableGroup(
502                                            permissionChecker, curLayout, controlPanelCategory,
503                                            ActionKeys.VIEW)) {
504    
505                                    return true;
506                            }
507                    }
508    
509                    return false;
510            }
511    
512    }