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.security.permission;
016    
017    import com.liferay.portal.NoSuchResourceException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.SetUtil;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.GroupConstants;
029    import com.liferay.portal.model.GroupedModel;
030    import com.liferay.portal.model.Layout;
031    import com.liferay.portal.model.Organization;
032    import com.liferay.portal.model.Permission;
033    import com.liferay.portal.model.PermissionedModel;
034    import com.liferay.portal.model.PortletConstants;
035    import com.liferay.portal.model.Resource;
036    import com.liferay.portal.model.ResourceBlockConstants;
037    import com.liferay.portal.model.ResourceConstants;
038    import com.liferay.portal.model.Role;
039    import com.liferay.portal.model.RoleConstants;
040    import com.liferay.portal.model.Team;
041    import com.liferay.portal.model.UserGroup;
042    import com.liferay.portal.security.permission.comparator.PermissionActionIdComparator;
043    import com.liferay.portal.service.GroupLocalServiceUtil;
044    import com.liferay.portal.service.LayoutLocalServiceUtil;
045    import com.liferay.portal.service.OrganizationLocalServiceUtil;
046    import com.liferay.portal.service.PermissionLocalServiceUtil;
047    import com.liferay.portal.service.ResourceBlockLocalServiceUtil;
048    import com.liferay.portal.service.ResourceLocalServiceUtil;
049    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
050    import com.liferay.portal.service.RoleLocalServiceUtil;
051    import com.liferay.portal.service.TeamLocalServiceUtil;
052    import com.liferay.portal.service.UserGroupLocalServiceUtil;
053    import com.liferay.portal.service.permission.PortletPermissionUtil;
054    import com.liferay.portal.util.PropsValues;
055    import com.liferay.util.UniqueList;
056    
057    import java.util.ArrayList;
058    import java.util.Collections;
059    import java.util.HashMap;
060    import java.util.LinkedHashMap;
061    import java.util.List;
062    import java.util.Map;
063    import java.util.Set;
064    
065    import org.apache.commons.lang.time.StopWatch;
066    
067    /**
068     * @author Charles May
069     * @author Brian Wing Shun Chan
070     * @author Raymond Augé
071     * @author Wesley Gong
072     * @author Connor McKay
073     */
074    public class AdvancedPermissionChecker extends BasePermissionChecker {
075    
076            @Override
077            public AdvancedPermissionChecker clone() {
078                    return new AdvancedPermissionChecker();
079            }
080    
081            @Override
082            public long[] getRoleIds(long userId, long groupId) {
083                    PermissionCheckerBag bag = null;
084    
085                    try {
086                            bag = getUserBag(userId, groupId);
087                    }
088                    catch (Exception e) {
089                    }
090    
091                    if (bag != null) {
092                            if (checkGuest) {
093                                    Set<Long> roleIds = SetUtil.fromArray(bag.getRoleIds());
094    
095                                    try {
096                                            PermissionCheckerBag guestBag = getGuestUserBag();
097    
098                                            if (guestBag != null) {
099                                                    for (long roleId : guestBag.getRoleIds()) {
100                                                            roleIds.add(roleId);
101                                                    }
102                                            }
103                                    }
104                                    catch (Exception e) {
105                                    }
106    
107                                    return ArrayUtil.toArray(
108                                            roleIds.toArray(new Long[roleIds.size()]));
109                            }
110                            else {
111                                    return bag.getRoleIds();
112                            }
113                    }
114    
115                    return PermissionChecker.DEFAULT_ROLE_IDS;
116            }
117    
118            @Override
119            public List<Long> getGuestResourceBlockIds(
120                    long companyId, long groupId, String name, String actionId) {
121    
122                    try {
123                            ResourceBlockIdsBag resourceBlockIdsBag =
124                                    getGuestResourceBlockIdsBag(companyId, groupId, name);
125    
126                            return ResourceBlockLocalServiceUtil.getResourceBlockIds(
127                                    resourceBlockIdsBag, name, actionId);
128                    }
129                    catch (Exception e) {
130                    }
131    
132                    return Collections.emptyList();
133            }
134    
135            public ResourceBlockIdsBag getGuestResourceBlockIdsBag(
136                            long companyId, long groupId, String name)
137                    throws Exception {
138    
139                    // checkGuest is irrelevant for the guest role, so it is assumed true
140    
141                    ResourceBlockIdsBag resourceBlockIdsBag =
142                            PermissionCacheUtil.getResourceBlockIdsBag(
143                                    companyId, groupId, defaultUserId, name, true);
144    
145                    if (resourceBlockIdsBag != null) {
146                            return resourceBlockIdsBag;
147                    }
148    
149                    try {
150                            PermissionCheckerBag bag = getGuestUserBag();
151    
152                            long[] roleIds = bag.getRoleIds();
153    
154                            resourceBlockIdsBag =
155                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
156                                            getCompanyId(), groupId, name, roleIds);
157    
158                            PermissionCacheUtil.putResourceBlockIdsBag(
159                                    companyId, groupId, defaultUserId, name, true,
160                                    resourceBlockIdsBag);
161    
162                            return resourceBlockIdsBag;
163                    }
164                    finally {
165                            if (resourceBlockIdsBag == null) {
166                                    resourceBlockIdsBag = new ResourceBlockIdsBag();
167                            }
168    
169                            PermissionCacheUtil.putResourceBlockIdsBag(
170                                    companyId, defaultUserId, groupId, name, true,
171                                    resourceBlockIdsBag);
172                    }
173            }
174    
175            /**
176             * Returns the permission checker bag for the guest user.
177             *
178             * @return the permission checker bag for the guest user
179             * @throws Exception if an exception occurred
180             */
181            public PermissionCheckerBag getGuestUserBag() throws Exception {
182                    Group guestGroup = GroupLocalServiceUtil.getGroup(
183                            getCompanyId(), GroupConstants.GUEST);
184    
185                    PermissionCheckerBag bag = PermissionCacheUtil.getBag(
186                            defaultUserId, guestGroup.getGroupId());
187    
188                    if (bag == null) {
189                            try {
190                                    List<Group> groups = new ArrayList<Group>();
191    
192                                    groups.add(guestGroup);
193    
194                                    List<Role> roles = RoleLocalServiceUtil.getUserRelatedRoles(
195                                            defaultUserId, groups);
196    
197                                    bag = new PermissionCheckerBagImpl(
198                                            defaultUserId, new ArrayList<Group>(),
199                                            new ArrayList<Organization>(), new ArrayList<Group>(),
200                                            new ArrayList<Group>(), groups, roles);
201                            }
202                            finally {
203                                    if (bag == null) {
204                                            bag = new PermissionCheckerBagImpl(
205                                                    defaultUserId, new ArrayList<Group>(),
206                                                    new ArrayList<Organization>(), new ArrayList<Group>(),
207                                                    new ArrayList<Group>(), new ArrayList<Group>(),
208                                                    new ArrayList<Role>());
209                                    }
210    
211                                    PermissionCacheUtil.putBag(
212                                            defaultUserId, guestGroup.getGroupId(), bag);
213                            }
214                    }
215    
216                    return bag;
217            }
218    
219            @Override
220            public List<Long> getOwnerResourceBlockIds(
221                    long companyId, long groupId, String name, String actionId) {
222    
223                    try {
224                            ResourceBlockIdsBag resourceBlockIdsBag =
225                                    getOwnerResourceBlockIdsBag(companyId, groupId, name);
226    
227                            return ResourceBlockLocalServiceUtil.getResourceBlockIds(
228                                    resourceBlockIdsBag, name, actionId);
229                    }
230                    catch (Exception e) {
231                    }
232    
233                    return Collections.emptyList();
234            }
235    
236            public ResourceBlockIdsBag getOwnerResourceBlockIdsBag(
237                            long companyId, long groupId, String name)
238                    throws SystemException {
239    
240                    // checkGuest is irrelevant for the owner role, so it is assumed true
241    
242                    ResourceBlockIdsBag resourceBlockIdsBag =
243                            PermissionCacheUtil.getResourceBlockIdsBag(
244                                    companyId, groupId, ResourceBlockConstants.OWNER_USER_ID, name,
245                                    true);
246    
247                    if (resourceBlockIdsBag != null) {
248                            return resourceBlockIdsBag;
249                    }
250    
251                    try {
252                            long[] roleIds = {getOwnerRoleId()};
253    
254                            resourceBlockIdsBag =
255                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
256                                            getCompanyId(), groupId, name, roleIds);
257    
258                            PermissionCacheUtil.putResourceBlockIdsBag(
259                                    companyId, groupId, ResourceBlockConstants.OWNER_USER_ID, name,
260                                    true, resourceBlockIdsBag);
261    
262                            return resourceBlockIdsBag;
263                    }
264                    finally {
265                            if (resourceBlockIdsBag == null) {
266                                    resourceBlockIdsBag = new ResourceBlockIdsBag();
267                            }
268    
269                            PermissionCacheUtil.putResourceBlockIdsBag(
270                                    companyId, ResourceBlockConstants.OWNER_USER_ID, groupId, name,
271                                    true, resourceBlockIdsBag);
272                    }
273            }
274    
275            @Override
276            public List<Long> getResourceBlockIds(
277                    long companyId, long groupId, long userId, String name,
278                    String actionId) {
279    
280                    try {
281                            ResourceBlockIdsBag resourceBlockIdsBag =
282                                    getResourceBlockIdsBag(companyId, groupId, userId, name);
283    
284                            return ResourceBlockLocalServiceUtil.getResourceBlockIds(
285                                    resourceBlockIdsBag, name, actionId);
286                    }
287                    catch (Exception e) {
288                    }
289    
290                    return Collections.emptyList();
291            }
292    
293            public ResourceBlockIdsBag getResourceBlockIdsBag(
294                            long companyId, long groupId, long userId, String name)
295                    throws Exception {
296    
297                    ResourceBlockIdsBag resourceBlockIdsBag =
298                            PermissionCacheUtil.getResourceBlockIdsBag(
299                                    companyId, groupId, userId, name, checkGuest);
300    
301                    if (resourceBlockIdsBag != null) {
302                            return resourceBlockIdsBag;
303                    }
304    
305                    try {
306                            long[] roleIds = getRoleIds(userId, groupId);
307    
308                            resourceBlockIdsBag =
309                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
310                                            getCompanyId(), groupId, name, roleIds);
311    
312                            PermissionCacheUtil.putResourceBlockIdsBag(
313                                    companyId, groupId, userId, name, checkGuest,
314                                    resourceBlockIdsBag);
315    
316                            return resourceBlockIdsBag;
317                    }
318                    finally {
319                            if (resourceBlockIdsBag == null) {
320                                    resourceBlockIdsBag = new ResourceBlockIdsBag();
321                            }
322    
323                            PermissionCacheUtil.putResourceBlockIdsBag(
324                                    companyId, userId, groupId, name, checkGuest,
325                                    resourceBlockIdsBag);
326                    }
327            }
328    
329            /**
330             * Returns the permission checker bag for the user and group. Users can have
331             * different roles and permissions in different groups.
332             *
333             * @param  userId the primary key of the user
334             * @param  groupId the primary key of the group
335             * @return the permission checker bag for the user and group
336             * @throws Exception if a user or group with the primary key could not be
337             *         found
338             */
339            public PermissionCheckerBag getUserBag(long userId, long groupId)
340                    throws Exception {
341    
342                    PermissionCheckerBag bag = PermissionCacheUtil.getBag(userId, groupId);
343    
344                    if (bag != null) {
345                            return bag;
346                    }
347    
348                    try {
349                            Group group = null;
350    
351                            if (groupId > 0) {
352                                    group = GroupLocalServiceUtil.getGroup(groupId);
353    
354                                    if (group.isLayout()) {
355                                            long parentGroupId = group.getParentGroupId();
356    
357                                            if (parentGroupId > 0) {
358                                                    group = GroupLocalServiceUtil.getGroup(parentGroupId);
359                                            }
360                                    }
361                            }
362    
363                            List<Group> userGroups = GroupLocalServiceUtil.getUserGroups(
364                                    userId, true);
365    
366                            List<Organization> userOrgs = getUserOrgs(userId);
367    
368                            List<Group> userOrgGroups =
369                                    GroupLocalServiceUtil.getOrganizationsGroups(userOrgs);
370    
371                            List<UserGroup> userUserGroups =
372                                    UserGroupLocalServiceUtil.getUserUserGroups(userId);
373    
374                            List<Group> userUserGroupGroups =
375                                    GroupLocalServiceUtil.getUserGroupsGroups(userUserGroups);
376    
377                            List<Group> groups = new ArrayList<Group>(
378                                    userGroups.size() + userOrgGroups.size() +
379                                            userUserGroupGroups.size());
380    
381                            groups.addAll(userGroups);
382                            groups.addAll(userOrgGroups);
383                            groups.addAll(userUserGroupGroups);
384    
385                            List<Role> roles = new UniqueList<Role>();
386    
387                            if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 3) ||
388                                    (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 4) ||
389                                    (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) ||
390                                    (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6)) {
391    
392                                    if (groups.size() > 0) {
393                                            List<Role> userRelatedRoles=
394                                                    RoleLocalServiceUtil.getUserRelatedRoles(
395                                                            userId, groups);
396    
397                                            roles.addAll(userRelatedRoles);
398                                    }
399                                    else {
400                                            roles.addAll(RoleLocalServiceUtil.getUserRoles(userId));
401                                    }
402    
403                                    List<Role> userGroupRoles =
404                                            RoleLocalServiceUtil.getUserGroupRoles(userId, groupId);
405    
406                                    roles.addAll(userGroupRoles);
407    
408                                    List<Role> userGroupGroupRoles =
409                                            RoleLocalServiceUtil.getUserGroupGroupRoles(
410                                                    userId, groupId);
411    
412                                    roles.addAll(userGroupGroupRoles);
413    
414                                    if (group != null) {
415                                            if (group.isOrganization() &&
416                                                    userOrgGroups.contains(group)) {
417    
418                                                    Role organizationUserRole =
419                                                            RoleLocalServiceUtil.getRole(
420                                                                    group.getCompanyId(),
421                                                                    RoleConstants.ORGANIZATION_USER);
422    
423                                                    roles.add(organizationUserRole);
424                                            }
425    
426                                            if (group.isSite() &&
427                                                    (userGroups.contains(group) ||
428                                                     userOrgGroups.contains(group))) {
429    
430                                                    Role siteMemberRole = RoleLocalServiceUtil.getRole(
431                                                            group.getCompanyId(), RoleConstants.SITE_MEMBER);
432    
433                                                    roles.add(siteMemberRole);
434                                            }
435    
436                                            if ((group.isOrganization() &&
437                                                     userOrgGroups.contains(group)) ||
438                                                    (group.isSite() && userGroups.contains(group))) {
439    
440                                                    addTeamRoles(userId, group, roles);
441                                            }
442                                    }
443                            }
444                            else {
445                                    roles = new ArrayList<Role>();
446                            }
447    
448                            bag = new PermissionCheckerBagImpl(
449                                    userId, userGroups, userOrgs, userOrgGroups,
450                                    userUserGroupGroups, groups, roles);
451    
452                            return bag;
453                    }
454                    finally {
455                            if (bag == null) {
456                                    bag = new PermissionCheckerBagImpl(
457                                            userId, new ArrayList<Group>(),
458                                            new ArrayList<Organization>(), new ArrayList<Group>(),
459                                            new ArrayList<Group>(), new ArrayList<Group>(),
460                                            new ArrayList<Role>());
461                            }
462    
463                            PermissionCacheUtil.putBag(userId, groupId, bag);
464                    }
465            }
466    
467            public boolean hasOwnerPermission(
468                    long companyId, String name, String primKey, long ownerId,
469                    String actionId) {
470    
471                    if (ownerId != getUserId()) {
472                            return false;
473                    }
474    
475                    if (ownerId == defaultUserId) {
476                            if (actionId.equals(ActionKeys.VIEW)) {
477                                    return true;
478                            }
479                            else {
480                                    return false;
481                            }
482                    }
483    
484                    try {
485                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
486                                    if (ResourceBlockLocalServiceUtil.isSupported(name)) {
487                                            PermissionedModel permissionedModel =
488                                                    ResourceBlockLocalServiceUtil.getPermissionedModel(
489                                                            name, GetterUtil.getLong(primKey));
490    
491                                            long groupId = 0;
492    
493                                            if (permissionedModel instanceof GroupedModel) {
494                                                    GroupedModel groupedModel =
495                                                            (GroupedModel)permissionedModel;
496    
497                                                    groupId = groupedModel.getGroupId();
498                                            }
499    
500                                            ResourceBlockIdsBag resourceBlockIdsBag =
501                                                    getOwnerResourceBlockIdsBag(companyId, groupId, name);
502    
503                                            return ResourceBlockLocalServiceUtil.hasPermission(
504                                                    name, permissionedModel, actionId, resourceBlockIdsBag);
505                                    }
506    
507                                    return ResourcePermissionLocalServiceUtil.hasResourcePermission(
508                                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL,
509                                            primKey, getOwnerRoleId(), actionId);
510                            }
511    
512                            ResourceActionsUtil.checkAction(name, actionId);
513    
514                            Resource resource = ResourceLocalServiceUtil.getResource(
515                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
516    
517                            List<Permission> permissions =
518                                    PermissionLocalServiceUtil.getRolePermissions(
519                                            getOwnerRoleId(), resource.getResourceId());
520    
521                            int pos = Collections.binarySearch(
522                                    permissions, actionId, new PermissionActionIdComparator());
523    
524                            if (pos >= 0) {
525                                    return true;
526                            }
527                    }
528                    catch (Exception e) {
529                            if (_log.isDebugEnabled()) {
530                                    _log.debug(e, e);
531                            }
532                    }
533    
534                    return false;
535            }
536    
537            public boolean hasPermission(
538                    long groupId, String name, String primKey, String actionId) {
539    
540                    StopWatch stopWatch = null;
541    
542                    if (_log.isDebugEnabled()) {
543                            stopWatch = new StopWatch();
544    
545                            stopWatch.start();
546                    }
547    
548                    Group group = null;
549    
550                    // If the current group is a staging group, check the live group. If the
551                    // current group is a scope group for a layout, check the original
552                    // group.
553    
554                    try {
555                            if (groupId > 0) {
556                                    group = GroupLocalServiceUtil.getGroup(groupId);
557    
558                                    if (group.isUser() && (group.getClassPK() == getUserId())) {
559                                            group = GroupLocalServiceUtil.getGroup(
560                                                    getCompanyId(), GroupConstants.USER_PERSONAL_SITE);
561    
562                                            groupId = group.getGroupId();
563                                    }
564    
565                                    if (group.isLayout()) {
566                                            Layout layout = LayoutLocalServiceUtil.getLayout(
567                                                    group.getClassPK());
568    
569                                            groupId = layout.getGroupId();
570    
571                                            group = GroupLocalServiceUtil.getGroup(groupId);
572                                    }
573    
574                                    if (group.isStagingGroup()) {
575                                            if (primKey.equals(String.valueOf(groupId))) {
576                                                    primKey = String.valueOf(group.getLiveGroupId());
577                                            }
578    
579                                            groupId = group.getLiveGroupId();
580                                            group = group.getLiveGroup();
581                                    }
582                            }
583                    }
584                    catch (Exception e) {
585                            _log.error(e, e);
586                    }
587    
588                    Boolean value = PermissionCacheUtil.getPermission(
589                            user.getUserId(), signedIn, checkGuest, groupId, name, primKey,
590                            actionId);
591    
592                    if (value == null) {
593                            try {
594                                    value = Boolean.valueOf(
595                                            hasPermissionImpl(groupId, name, primKey, actionId));
596    
597                                    if (_log.isDebugEnabled()) {
598                                            _log.debug(
599                                                    "Checking permission for " + groupId + " " + name +
600                                                            " " + primKey + " " + actionId + " takes " +
601                                                                    stopWatch.getTime() + " ms");
602                                    }
603                            }
604                            finally {
605                                    if (value == null) {
606                                            value = Boolean.FALSE;
607                                    }
608    
609                                    PermissionCacheUtil.putPermission(
610                                            user.getUserId(), signedIn, checkGuest, groupId, name,
611                                            primKey, actionId, value);
612                            }
613                    }
614    
615                    return value.booleanValue();
616            }
617    
618            public boolean hasUserPermission(
619                    long groupId, String name, String primKey, String actionId,
620                    boolean checkAdmin) {
621    
622                    try {
623                            return hasUserPermissionImpl(
624                                    groupId, name, primKey, actionId, checkAdmin);
625                    }
626                    catch (Exception e) {
627                            _log.error(e, e);
628    
629                            return false;
630                    }
631            }
632    
633            public boolean isCompanyAdmin() {
634                    try {
635                            return isCompanyAdminImpl();
636                    }
637                    catch (Exception e) {
638                            _log.error(e, e);
639    
640                            return false;
641                    }
642            }
643    
644            public boolean isCompanyAdmin(long companyId) {
645                    try {
646                            return isCompanyAdminImpl(companyId);
647                    }
648                    catch (Exception e) {
649                            _log.error(e, e);
650    
651                            return false;
652                    }
653            }
654    
655            public boolean isGroupAdmin(long groupId) {
656                    try {
657                            return isGroupAdminImpl(groupId);
658                    }
659                    catch (Exception e) {
660                            _log.error(e, e);
661    
662                            return false;
663                    }
664            }
665    
666            public boolean isGroupOwner(long groupId) {
667                    try {
668                            return isGroupOwnerImpl(groupId);
669                    }
670                    catch (Exception e) {
671                            _log.error(e, e);
672    
673                            return false;
674                    }
675            }
676    
677            protected void addTeamRoles(long userId, Group group, List<Role> roles)
678                    throws Exception {
679    
680                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) ||
681                            (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6)) {
682    
683                            List<Team> userTeams = TeamLocalServiceUtil.getUserTeams(
684                                    userId, group.getGroupId());
685    
686                            for (Team team : userTeams) {
687                                    Role role = RoleLocalServiceUtil.getTeamRole(
688                                            team.getCompanyId(), team.getTeamId());
689    
690                                    roles.add(role);
691                            }
692    
693                            LinkedHashMap<String, Object> teamParams =
694                                    new LinkedHashMap<String, Object>();
695    
696                            teamParams.put("usersUserGroups", userId);
697    
698                            List<Team> userGroupTeams = TeamLocalServiceUtil.search(
699                                    group.getGroupId(), null, null, teamParams, QueryUtil.ALL_POS,
700                                    QueryUtil.ALL_POS, null);
701    
702                            for (Team team : userGroupTeams) {
703                                    Role role = RoleLocalServiceUtil.getTeamRole(
704                                            team.getCompanyId(), team.getTeamId());
705    
706                                    roles.add(role);
707                            }
708                    }
709            }
710    
711            /**
712             * Returns representations of the resource at each scope level.
713             *
714             * <p>
715             * For example, if the class name and primary key of a blog entry were
716             * passed to this method, it would return a resource for the blog entry
717             * itself (individual scope), a resource representing all blog entries
718             * within its group (group scope), a resource standing for all blog entries
719             * within a group the user has a suitable role in (group-template scope),
720             * and a resource signifying all blog entries within the company (company
721             * scope).
722             * </p>
723             *
724             * @param  companyId the primary key of the company
725             * @param  groupId the primary key of the group containing the resource
726             * @param  name the resource's name, which can be either a class name or a
727             *         portlet ID
728             * @param  primKey the primary key of the resource
729             * @param  actionId unused
730             * @return representations of the resource at each scope level
731             * @throws Exception if an exception occurred
732             */
733            protected List<Resource> getResources(
734                            long companyId, long groupId, String name, String primKey,
735                            String actionId)
736                    throws Exception {
737    
738                    // Individual
739    
740                    List<Resource> resources = new ArrayList<Resource>(4);
741    
742                    try {
743                            Resource resource = ResourceLocalServiceUtil.getResource(
744                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
745    
746                            resources.add(resource);
747                    }
748                    catch (NoSuchResourceException nsre) {
749                            if (_log.isWarnEnabled()) {
750                                    _log.warn(
751                                            "Resource " + companyId + " " + name + " " +
752                                                    ResourceConstants.SCOPE_INDIVIDUAL + " " + primKey +
753                                                            " does not exist");
754                            }
755                    }
756    
757                    // Group
758    
759                    try {
760                            if (groupId > 0) {
761                                    Resource resource = ResourceLocalServiceUtil.getResource(
762                                            companyId, name, ResourceConstants.SCOPE_GROUP,
763                                            String.valueOf(groupId));
764    
765                                    resources.add(resource);
766                            }
767                    }
768                    catch (NoSuchResourceException nsre) {
769                            if (_log.isWarnEnabled()) {
770                                    _log.warn(
771                                            "Resource " + companyId + " " + name + " " +
772                                                    ResourceConstants.SCOPE_GROUP + " " + groupId +
773                                                            " does not exist");
774                            }
775                    }
776    
777                    // Group template
778    
779                    try {
780                            if (signedIn && (groupId > 0)) {
781                                    Resource resource = ResourceLocalServiceUtil.getResource(
782                                            companyId, name, ResourceConstants.SCOPE_GROUP_TEMPLATE,
783                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID));
784    
785                                    resources.add(resource);
786                            }
787                    }
788                    catch (NoSuchResourceException nsre) {
789                            if (_log.isWarnEnabled()) {
790                                    _log.warn(
791                                            "Resource " + companyId + " " + name + " " +
792                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE + " " +
793                                                            GroupConstants.DEFAULT_PARENT_GROUP_ID +
794                                                                    " does not exist");
795                            }
796                    }
797    
798                    // Company
799    
800                    try {
801                            Resource resource = ResourceLocalServiceUtil.getResource(
802                                    companyId, name, ResourceConstants.SCOPE_COMPANY,
803                                    String.valueOf(companyId));
804    
805                            resources.add(resource);
806                    }
807                    catch (NoSuchResourceException nsre) {
808                            if (_log.isWarnEnabled()) {
809                                    _log.warn(
810                                            "Resource " + companyId + " " + name + " " +
811                                                    ResourceConstants.SCOPE_COMPANY + " " + companyId +
812                                                            " does not exist");
813                            }
814                    }
815    
816                    return resources;
817            }
818    
819            /**
820             * Returns all of the organizations that the user is a member of, including
821             * their parent organizations.
822             *
823             * @param  userId the primary key of the user
824             * @return all of the organizations that the user is a member of, including
825             *         their parent organizations
826             * @throws Exception if a user with the primary key could not be found
827             */
828            protected List<Organization> getUserOrgs(long userId) throws Exception {
829                    List<Organization> userOrgs =
830                            OrganizationLocalServiceUtil.getUserOrganizations(userId);
831    
832                    if (userOrgs.size() == 0) {
833                            return userOrgs;
834                    }
835    
836                    List<Organization> organizations = new UniqueList<Organization>();
837    
838                    for (Organization organization : userOrgs) {
839                            if (!organizations.contains(organization)) {
840                                    organizations.add(organization);
841    
842                                    List<Organization> ancestorOrganizations =
843                                            OrganizationLocalServiceUtil.getParentOrganizations(
844                                                    organization.getOrganizationId());
845    
846                                    organizations.addAll(ancestorOrganizations);
847                            }
848                    }
849    
850                    return organizations;
851            }
852    
853            protected boolean hasGuestPermission(
854                            long groupId, String name, String primKey, String actionId)
855                    throws Exception {
856    
857                    ResourceActionsUtil.checkAction(name, actionId);
858    
859                    if (name.indexOf(CharPool.PERIOD) != -1) {
860    
861                            // Check unsupported model actions
862    
863                            List<String> actions = ResourceActionsUtil.
864                                    getModelResourceGuestUnsupportedActions(name);
865    
866                            if (actions.contains(actionId)) {
867                                    return false;
868                            }
869                    }
870                    else {
871    
872                            // Check unsupported portlet actions
873    
874                            List<String> actions = ResourceActionsUtil.
875                                    getPortletResourceGuestUnsupportedActions(name);
876    
877                            if (actions.contains(actionId)) {
878                                    return false;
879                            }
880                    }
881    
882                    long companyId = user.getCompanyId();
883    
884                    List<Resource> resources = getResources(
885                            companyId, groupId, name, primKey, actionId);
886    
887                    PermissionCheckerBag bag = getGuestUserBag();
888    
889                    try {
890                            if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
891                                    ResourceBlockLocalServiceUtil.isSupported(name)) {
892    
893                                    ResourceBlockIdsBag resourceBlockIdsBag =
894                                            getGuestResourceBlockIdsBag(companyId, groupId, name);
895    
896                                    return ResourceBlockLocalServiceUtil.hasPermission(
897                                            name, GetterUtil.getLong(primKey), actionId,
898                                            resourceBlockIdsBag);
899                            }
900    
901                            return PermissionLocalServiceUtil.hasUserPermissions(
902                                    defaultUserId, groupId, resources, actionId, bag);
903                    }
904                    catch (Exception e) {
905                            _log.error(e, e);
906    
907                            return false;
908                    }
909            }
910    
911            protected boolean hasPermissionImpl(
912                    long groupId, String name, String primKey, String actionId) {
913    
914                    try {
915                            if (!signedIn) {
916                                    return hasGuestPermission(groupId, name, primKey, actionId);
917                            }
918    
919                            if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
920                                    ResourceBlockLocalServiceUtil.isSupported(name)) {
921    
922                                    // It is not necessary to check guest permissions separately,
923                                    // as the user's resource block IDs bag will already have the
924                                    // guest permissions in it if checkGuest is true.
925    
926                                    return hasUserPermission(
927                                            groupId, name, primKey, actionId, true);
928                            }
929    
930                            boolean value = false;
931    
932                            if (checkGuest) {
933                                    value = hasGuestPermission(groupId, name, primKey, actionId);
934                            }
935    
936                            if (!value) {
937                                    value = hasUserPermission(
938                                            groupId, name, primKey, actionId, true);
939                            }
940    
941                            return value;
942                    }
943                    catch (Exception e) {
944                            _log.error(e, e);
945    
946                            return false;
947                    }
948            }
949    
950            protected boolean hasUserPermissionImpl(
951                            long groupId, String name, String primKey, String actionId,
952                            boolean checkAdmin)
953                    throws Exception {
954    
955                    StopWatch stopWatch = null;
956    
957                    if (_log.isDebugEnabled()) {
958                            stopWatch = new StopWatch();
959    
960                            stopWatch.start();
961                    }
962    
963                    long companyId = user.getCompanyId();
964    
965                    boolean hasLayoutManagerPermission = true;
966    
967                    // Check if the layout manager has permission to do this action for the
968                    // current portlet
969    
970                    if ((Validator.isNotNull(name)) && (Validator.isNotNull(primKey)) &&
971                            (primKey.indexOf(PortletConstants.LAYOUT_SEPARATOR) != -1)) {
972    
973                            hasLayoutManagerPermission =
974                                    PortletPermissionUtil.hasLayoutManagerPermission(
975                                            name, actionId);
976                    }
977    
978                    if (checkAdmin &&
979                            (isCompanyAdminImpl(companyId) ||
980                             (isGroupAdminImpl(groupId) && hasLayoutManagerPermission))) {
981    
982                            return true;
983                    }
984    
985                    logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 1);
986    
987                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
988                            ResourceBlockLocalServiceUtil.isSupported(name)) {
989    
990                            ResourceBlockIdsBag resourceBlockIdsBag =
991                                    getResourceBlockIdsBag(companyId, groupId, getUserId(), name);
992    
993                            boolean value = ResourceBlockLocalServiceUtil.hasPermission(
994                                    name, GetterUtil.getLong(primKey), actionId,
995                                    resourceBlockIdsBag);
996    
997                            logHasUserPermission(
998                                    groupId, name, primKey, actionId, stopWatch, 2);
999    
1000                            return value;
1001                    }
1002    
1003                    List<Resource> resources = getResources(
1004                            companyId, groupId, name, primKey, actionId);
1005    
1006                    logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 3);
1007    
1008                    // Check if user has access to perform the action on the given
1009                    // resource scopes. The resources are scoped to check first for an
1010                    // individual class, then for the group that the class may belong
1011                    // to, and then for the company that the class belongs to.
1012    
1013                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1014    
1015                    boolean value = PermissionLocalServiceUtil.hasUserPermissions(
1016                            user.getUserId(), groupId, resources, actionId, bag);
1017    
1018                    logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 4);
1019    
1020                    return value;
1021            }
1022    
1023            protected boolean isCompanyAdminImpl() throws Exception {
1024                    return isCompanyAdminImpl(user.getCompanyId());
1025            }
1026    
1027            protected boolean isCompanyAdminImpl(long companyId) throws Exception {
1028                    if (!signedIn) {
1029                            return false;
1030                    }
1031    
1032                    if (isOmniadmin()) {
1033                            return true;
1034                    }
1035    
1036                    Boolean value = companyAdmins.get(companyId);
1037    
1038                    if (value == null) {
1039                            boolean hasAdminRole = RoleLocalServiceUtil.hasUserRole(
1040                                    user.getUserId(), companyId, RoleConstants.ADMINISTRATOR, true);
1041    
1042                            value = Boolean.valueOf(hasAdminRole);
1043    
1044                            companyAdmins.put(companyId, value);
1045                    }
1046    
1047                    return value.booleanValue();
1048            }
1049    
1050            protected boolean isGroupAdminImpl(long groupId) throws Exception {
1051                    if (!signedIn) {
1052                            return false;
1053                    }
1054    
1055                    if (isOmniadmin()) {
1056                            return true;
1057                    }
1058    
1059                    if (groupId <= 0) {
1060                            return false;
1061                    }
1062    
1063                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1064    
1065                    if (isCompanyAdmin(group.getCompanyId())) {
1066                            return true;
1067                    }
1068    
1069                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1070    
1071                    if (bag == null) {
1072                            _log.error("Bag should never be null");
1073                    }
1074    
1075                    if (bag.isGroupAdmin(this, group)) {
1076                            return true;
1077                    }
1078                    else {
1079                            return false;
1080                    }
1081            }
1082    
1083            protected boolean isGroupOwnerImpl(long groupId) throws Exception {
1084                    if (!signedIn) {
1085                            return false;
1086                    }
1087    
1088                    if (isOmniadmin()) {
1089                            return true;
1090                    }
1091    
1092                    if (groupId <= 0) {
1093                            return false;
1094                    }
1095    
1096                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1097    
1098                    if (isCompanyAdmin(group.getCompanyId())) {
1099                            return true;
1100                    }
1101    
1102                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1103    
1104                    if (bag == null) {
1105                            _log.error("Bag should never be null");
1106                    }
1107    
1108                    if (bag.isGroupOwner(this, group)) {
1109                            return true;
1110                    }
1111                    else {
1112                            return false;
1113                    }
1114            }
1115    
1116            protected void logHasUserPermission(
1117                    long groupId, String name, String primKey, String actionId,
1118                    StopWatch stopWatch, int block) {
1119    
1120                    if (!_log.isDebugEnabled()) {
1121                            return;
1122                    }
1123    
1124                    _log.debug(
1125                            "Checking user permission block " + block + " for " + groupId +
1126                                    " " + name + " " + primKey + " " + actionId + " takes " +
1127                                            stopWatch.getTime() + " ms");
1128            }
1129    
1130            /**
1131             * @deprecated
1132             */
1133            protected static final String RESULTS_SEPARATOR = "_RESULTS_SEPARATOR_";
1134    
1135            protected Map<Long, Boolean> companyAdmins = new HashMap<Long, Boolean>();
1136    
1137            private static Log _log = LogFactoryUtil.getLog(
1138                    AdvancedPermissionChecker.class);
1139    
1140    }