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