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