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 = UserLocalServiceUtil.getUserById(
189                            permissionChecker.getUserId());
190    
191                    if (!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                                            parentLayoutId);
243    
244                                    if (contains(
245                                                    permissionChecker, parentLayout, controlPanelCategory,
246                                                    actionId)) {
247    
248                                            return true;
249                                    }
250    
251                                    parentLayoutId = parentLayout.getParentLayoutId();
252                            }
253                    }
254    
255                    int resourcePermissionsCount =
256                            ResourcePermissionLocalServiceUtil.getResourcePermissionsCount(
257                                    layout.getCompanyId(), Layout.class.getName(),
258                                    ResourceConstants.SCOPE_INDIVIDUAL,
259                                    String.valueOf(layout.getPlid()));
260    
261                    if (resourcePermissionsCount == 0) {
262                            boolean addGroupPermission = true;
263                            boolean addGuestPermission = true;
264    
265                            if (layout.isPrivateLayout()) {
266                                    addGuestPermission = false;
267                            }
268    
269                            ResourceLocalServiceUtil.addResources(
270                                    layout.getCompanyId(), layout.getGroupId(), 0,
271                                    Layout.class.getName(), layout.getPlid(), false,
272                                    addGroupPermission, addGuestPermission);
273                    }
274    
275                    return permissionChecker.hasPermission(
276                            layout.getGroupId(), Layout.class.getName(), layout.getPlid(),
277                            actionId);
278            }
279    
280            public boolean containsWithoutViewableGroup(
281                            PermissionChecker permissionChecker, Layout layout,
282                            String controlPanelCategory, String actionId)
283                    throws PortalException, SystemException {
284    
285                    return containsWithoutViewableGroup(
286                            permissionChecker, layout, controlPanelCategory, true, actionId);
287            }
288    
289            protected boolean containsWithViewableGroup(
290                            PermissionChecker permissionChecker, Layout layout,
291                            String controlPanelCategory, boolean checkViewableGroup,
292                            String actionId)
293                    throws PortalException, SystemException {
294    
295                    if (actionId.equals(ActionKeys.VIEW) && checkViewableGroup) {
296                            return isViewableGroup(
297                                    permissionChecker, layout, controlPanelCategory,
298                                    checkViewableGroup);
299                    }
300    
301                    return containsWithoutViewableGroup(
302                            permissionChecker, layout, controlPanelCategory, actionId);
303            }
304    
305            protected boolean isAttemptToModifyLockedLayout(
306                    Layout layout, String actionId) {
307    
308                    if (!SitesUtil.isLayoutUpdateable(layout) &&
309                            (ActionKeys.CUSTOMIZE.equals(actionId) ||
310                             ActionKeys.UPDATE.equals(actionId))) {
311    
312                            return true;
313                    }
314    
315                    return false;
316            }
317    
318            protected boolean isViewableGroup(
319                            PermissionChecker permissionChecker, Layout layout,
320                            String controlPanelCategory, boolean checkResourcePermission)
321                    throws PortalException, SystemException {
322    
323                    Group group = GroupLocalServiceUtil.getGroup(layout.getGroupId());
324    
325                    // Inactive sites are not viewable
326    
327                    if (!group.isActive()) {
328                            return false;
329                    }
330                    else if (group.isStagingGroup()) {
331                            Group liveGroup = group.getLiveGroup();
332    
333                            if (!liveGroup.isActive()) {
334                                    return false;
335                            }
336                    }
337    
338                    // User private layouts are only viewable by the user and anyone who can
339                    // update the user. The user must also be active.
340    
341                    if (group.isUser()) {
342                            long groupUserId = group.getClassPK();
343    
344                            if (groupUserId == permissionChecker.getUserId()) {
345                                    return true;
346                            }
347    
348                            User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
349    
350                            if (!groupUser.isActive()) {
351                                    return false;
352                            }
353    
354                            if (layout.isPrivateLayout()) {
355                                    if (GroupPermissionUtil.contains(
356                                                    permissionChecker, groupUser.getGroupId(),
357                                                    ActionKeys.MANAGE_LAYOUTS) ||
358                                            UserPermissionUtil.contains(
359                                                    permissionChecker, groupUserId,
360                                                    groupUser.getOrganizationIds(), ActionKeys.UPDATE)) {
361    
362                                            return true;
363                                    }
364    
365                                    return false;
366                            }
367                    }
368    
369                    // If the current group is staging, only users with editorial rights
370                    // can access it
371    
372                    if (group.isStagingGroup()) {
373                            if (GroupPermissionUtil.contains(
374                                            permissionChecker, group.getGroupId(),
375                                            ActionKeys.VIEW_STAGING)) {
376    
377                                    return true;
378                            }
379    
380                            return false;
381                    }
382    
383                    // Control panel layouts are only viewable by authenticated users
384    
385                    if (group.isControlPanel()) {
386                            if (!permissionChecker.isSignedIn()) {
387                                    return false;
388                            }
389    
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(), ActionKeys.UPDATE)) {
412    
413                                    return true;
414                            }
415    
416                            if (layout.isPrivateLayout() &&
417                                    !permissionChecker.isGroupMember(group.getGroupId())) {
418    
419                                    return false;
420                            }
421                    }
422    
423                    // Organization site layouts are also viewable by users who belong to
424                    // the organization or by users who can update organization
425    
426                    if (group.isCompany()) {
427                            return false;
428                    }
429                    else if (group.isLayoutPrototype()) {
430                            if (LayoutPrototypePermissionUtil.contains(
431                                            permissionChecker, group.getClassPK(), ActionKeys.VIEW)) {
432    
433                                    return true;
434                            }
435    
436                            return false;
437                    }
438                    else if (group.isLayoutSetPrototype()) {
439                            if (LayoutSetPrototypePermissionUtil.contains(
440                                            permissionChecker, group.getClassPK(), ActionKeys.VIEW)) {
441    
442                                    return true;
443                            }
444    
445                            return false;
446                    }
447                    else if (group.isOrganization()) {
448                            long organizationId = group.getOrganizationId();
449    
450                            if (OrganizationLocalServiceUtil.hasUserOrganization(
451                                            permissionChecker.getUserId(), organizationId, false,
452                                            false)) {
453    
454                                    return true;
455                            }
456                            else if (OrganizationPermissionUtil.contains(
457                                                    permissionChecker, organizationId, ActionKeys.UPDATE)) {
458    
459                                    return true;
460                            }
461    
462                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
463                                    List<Organization> userOrgs =
464                                            OrganizationLocalServiceUtil.getUserOrganizations(
465                                                    permissionChecker.getUserId());
466    
467                                    for (Organization organization : userOrgs) {
468                                            for (Organization ancestorOrganization :
469                                                            organization.getAncestors()) {
470    
471                                                    if (organizationId ==
472                                                                    ancestorOrganization.getOrganizationId()) {
473    
474                                                            return true;
475                                                    }
476                                            }
477                                    }
478                            }
479                    }
480                    else if (group.isUserGroup()) {
481                            if (UserGroupPermissionUtil.contains(
482                                            permissionChecker, group.getClassPK(), ActionKeys.UPDATE)) {
483    
484                                    return true;
485                            }
486                    }
487    
488                    // Only check the actual Layout if all of the above failed
489    
490                    if (containsWithoutViewableGroup(
491                                    permissionChecker, layout, controlPanelCategory,
492                                    ActionKeys.VIEW)) {
493    
494                            return true;
495                    }
496    
497                    // As a last resort, check if any top level pages are viewable by the
498                    // user
499    
500                    List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
501                            layout.getGroupId(), layout.isPrivateLayout(),
502                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
503    
504                    for (Layout curLayout : layouts) {
505                            if (!curLayout.isHidden() &&
506                                    containsWithoutViewableGroup(
507                                            permissionChecker, curLayout, controlPanelCategory,
508                                            ActionKeys.VIEW)) {
509    
510                                    return true;
511                            }
512                    }
513    
514                    return false;
515            }
516    
517    }