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