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